sql >> Database teknologi >  >> RDS >> PostgreSQL

Funktion til at returnere dynamisk sæt af kolonner for en given tabel

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?
Bortset fra

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.



  1. SQL Server-sikkerhedsovervejelser

  2. Hvordan ROWNUM fungerer i pagineringsforespørgsel?

  3. MariaDB UNDTAGET Operatør forklaret

  4. MariaDB SQL Set Operators