sql >> Databáze >  >> RDS >> PostgreSQL

Funkce pro vrácení dynamické sady sloupců pro danou tabulku

Řešení pro jednoduchý případ

Jak je vysvětleno v níže uvedených odpovědích, můžete použít registrované (řádkové) typy, a tak implicitně deklarovat návratový typ polymorfní funkce:

CREATE OR REPLACE FUNCTION public.get_table(_tbl_type anyelement)
  RETURNS SETOF anyelement AS
$func$
BEGIN
   RETURN QUERY EXECUTE format('TABLE %s', pg_typeof(_tbl_type));
END
$func$ LANGUAGE plpgsql;

Volejte:

SELECT * FROM public.get_table(NULL::public.users);  -- note the syntax!

Vrátí úplnou tabulku (se všemi uživatelskými sloupci).

Počkejte! Jak?

Podrobné vysvětlení v této související odpovědi, kapitola"Různé kompletní typy tabulek" :

  • Refaktorujte funkci PL/pgSQL tak, aby vrátila výstup různých SELECT dotazů

TABLE foo je zkratka pro SELECT * FROM foo :

  • Existuje zkratka pro SELECT * FROM?

2 kroky pro zcela dynamický návratový typ

Ale to, o co se snažíte, je přísně nemožné v jednom SQL příkaz.

Chci předat schema_name a table_name jako parametry pro funkci a získání seznamu záznamů podle column_visible pole v public.fields tabulka.

Neexistuje žádný přímý způsob, jak vrátit libovolný výběr sloupců (typ návratu není v době volání znám) z funkce – nebo jakéhokoli SQL příkaz. SQL vyžaduje znát počet, názvy a typy výsledných sloupců v době volání. Více ve 2. kapitole této související odpovědi:

  • Jak vygeneruji pivotované CROSS JOIN, kde výsledná definice tabulky není známa?

Existují různá řešení . Výsledek můžete zabalit do jednoho ze standardních typů dokumentů (json , jsonb , hstore , xml ).

Nebo vygenerujete dotaz jedním voláním funkce a provedete výsledek dalším:

CREATE OR REPLACE FUNCTION public.generate_get_table(_schema_name text, _table_name text)
  RETURNS text AS
$func$
   SELECT format('SELECT %s FROM %I.%I'
               , string_agg(quote_ident(column_name), ', ')
               , schema_name
               , table_name)
   FROM   fields
   WHERE  column_visible
   AND    schema_name = _schema_name 
   AND    table_name  = _table_name
   GROUP  BY schema_name, table_name
   ORDER  BY schema_name, table_name;
$func$  LANGUAGE sql;

Volejte:

SELECT public.generate_get_table('public', 'users');

Tím vytvoříte dotaz ve tvaru:

SELECT usr_id, usr FROM public.users;

Proveďte jej ve 2. kroku. (Možná budete chtít přidat čísla sloupců a sloupce pořadí.)
Nebo připojte \gexec v psql pro okamžité provedení vrácené hodnoty. Viz:

Jak vynutit vyhodnocení poddotazu před připojením / posunutím dolů na cizí server

Nezapomeňte se bránit SQL injection:

  • INSERT s názvem dynamické tabulky ve funkci spouštění
  • Definovat názvy tabulek a sloupců jako argumenty ve funkci plpgsql?
Strany

varchar(100) nedává příliš smysl pro identifikátory, které jsou ve standardním Postgresu omezeny na 63 znaků:

  • Maximální počet znaků ve štítcích (názvy tabulek, sloupce atd.)

Pokud rozumíte tomu, jak identifikátor objektu zadejte regclass funguje, můžete nahradit název schématu a tabulky singe regclass sloupec.



  1. Proč je Oracle tak pomalý, když předávám java.sql.Timestamp pro sloupec DATE?

  2. Jak zadat znak nového řádku v Oracle?

  3. Závažná chyba:Nezachycená chyba:Volání nedefinované funkce mysql_connect()

  4. Jak mohu importovat velký (14 GB) soubor výpisu MySQL do nové databáze MySQL?