sql >> Databasteknik >  >> RDS >> PostgreSQL

Funktion för att returnera dynamisk uppsättning kolumner för given tabell

Lösning för det enkla fallet

Som förklaras i de refererade svaren nedan kan du använda registrerade (rad) typer och därmed implicit deklarera returtypen för en polymorf funktion:

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;

Ring:

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

Returnerar hela tabellen (med alla användarkolumner).

Vänta! Hur?

Detaljerad förklaring i detta relaterade svar, kapitel"Olika kompletta tabelltyper" :

  • Refaktorera en PL/pgSQL-funktion för att returnera utdata från olika SELECT-frågor

TABLE foo är bara förkortning för SELECT * FROM foo :

  • Finns det en genväg för SELECT * FROM?

2 steg för helt dynamisk returtyp

Men det du försöker göra är strängt omöjligt i en singel SQL-kommando.

Jag vill skicka schema_name och table_name som parametrar för att fungera och få postlista, enligt column_visible fält i public.fields bord.

Det finns inget direkt sätt att returnera ett godtyckligt urval av kolumner (returtyp som inte är känd vid samtalstillfället) från en funktion - eller någon SQL kommando. SQL kräver att veta antal, namn och typer av resulterande kolumner vid anropstid. Mer i det andra kapitlet i detta relaterade svar:

  • Hur skapar jag en pivoterad CROSS JOIN där den resulterande tabelldefinitionen är okänd?

Det finns olika lösningar . Du kan slå in resultatet i en av standarddokumenttyperna (json , jsonb , hstore , xml ).

Eller du genererar frågan med ett funktionsanrop och kör resultatet med nästa:

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;

Ring:

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

Detta skapar en fråga av formuläret:

SELECT usr_id, usr FROM public.users;

Utför det i steg 2. (Du kanske vill lägga till kolumnnummer och ordna kolumner.)
Eller lägg till \gexec i psql för att exekvera returvärdet omedelbart. Se:

Hur man tvingar utvärdering av underfrågan innan man går med / trycker ner till främmande server

Se till att försvara dig mot SQL-injektion:

  • INSERT med dynamiskt tabellnamn i triggerfunktionen
  • Definiera tabell- och kolumnnamn som argument i en plpgsql-funktion?
Åsidosätts

varchar(100) är inte mycket meningsfullt för identifierare, som är begränsade till 63 tecken i standard Postgres:

  • Maximalt antal tecken i etiketter (tabellnamn, kolumner etc.)

Om du förstår hur objektidentifieraren skriver regclass fungerar, kan du ersätta schema och tabellnamn med en singe regclass kolumn.



  1. Finns det något sätt att köra en fråga i strängvärdet (som eval) i PostgreSQL?

  2. Hur kan jag få summan av flera datetime-värden?

  3. SQL Server-transaktionsloggen, del 1:Grunderna i loggning

  4. Installera WordPress med Nginx, MariaDB 10 och PHP 7 på Debian 9