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
ochtable_name
som parametrar för att fungera och få postlista, enligtcolumn_visible
fält ipublic.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?
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.