Løsning til den simple sag
Som forklaret i de refererede svar nedenfor, kan du bruge registrerede (række) typer og dermed implicit erklære returtypen for 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 til:
SELECT * FROM public.get_table(NULL::public.users); -- note the syntax!
Returnerer hele tabellen (med alle brugerkolonner).
Vent! Hvordan?
Detaljeret forklaring i dette relaterede svar, kapitel"Forskellige komplette tabeltyper" :
- Refaktorer en PL/pgSQL-funktion for at returnere output fra forskellige SELECT-forespørgsler
TABLE foo
er bare en forkortelse for SELECT * FROM foo
:
- Er der en genvej til SELECT * FROM?
2 trin for fuldstændig dynamisk returtype
Men det, du forsøger at gøre, er strengt umuligt i en enkelt SQL-kommando.
Jeg vil videregive schema_name
og table_name
som parametre til at fungere og få postliste i henhold til column_visible
felt i public.fields
tabel.
Der er ingen direkte måde at returnere et vilkårligt udvalg af kolonner (returtype ikke kendt på opkaldstidspunktet) fra en funktion - eller enhver SQL kommando. SQL kræver at kende antal, navne og typer af resulterende kolonner på opkaldstidspunktet. Mere i det 2. kapitel af dette relaterede svar:
- Hvordan genererer jeg en pivoteret CROSS JOIN, hvor den resulterende tabeldefinition er ukendt?
Der er forskellige løsninger . Du kan pakke resultatet ind i en af standarddokumenttyperne (json
, jsonb
, hstore
, xml
).
Eller du genererer forespørgslen med et funktionskald og udfører resultatet med det næste:
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 til:
SELECT public.generate_get_table('public', 'users');
Dette opretter en forespørgsel i formen:
SELECT usr_id, usr FROM public.users;
Udfør det i 2. trin. (Du vil måske tilføje kolonnenumre og rækkefølge kolonner.)
Eller tilføje \gexec
i psql for at udføre returværdien med det samme. Se:
Hvordan man tvinger evaluering af underforespørgsel, før man tilslutter sig/skubber ned til en fremmed server
Sørg for at forsvare dig mod SQL-injektion:
- INSERT med dynamisk tabelnavn i triggerfunktion
- Definer tabel- og kolonnenavne som argumenter i en plpgsql-funktion?
varchar(100)
giver ikke meget mening for identifikatorer, som er begrænset til 63 tegn i standard Postgres:
- Maksimalt antal tegn i etiketter (tabelnavne, kolonner osv.)
Hvis du forstår, hvordan objektidentifikatoren skriver regclass
fungerer, kan du erstatte skema og tabelnavn med en enkelt regclass
kolonne.