PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Funktion zum Zurückgeben eines dynamischen Satzes von Spalten für eine bestimmte Tabelle

Lösung für den einfachen Fall

Wie in den referenzierten Antworten unten erläutert, können Sie registrierte (Zeilen-)Typen verwenden und somit implizit den Rückgabetyp einer polymorphen Funktion deklarieren:

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;

Aufruf:

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

Gibt die vollständige Tabelle (mit allen Benutzerspalten) zurück.

Warte! Wie?

Ausführliche Erklärung in dieser zugehörigen Antwort, Kapitel "Verschiedene vollständige Tabellentypen" :

  • Refaktorisieren Sie eine PL/pgSQL-Funktion, um die Ausgabe verschiedener SELECT-Abfragen zurückzugeben

TABLE foo ist nur kurz für SELECT * FROM foo :

  • Gibt es eine Abkürzung für SELECT * FROM?

2 Schritte für vollständig dynamischen Rückgabetyp

Aber was Sie zu tun versuchen, ist streng unmöglich in einem einzelnen SQL-Befehl.

Ich möchte schema_name übergeben und table_name als Parameter zum Funktionieren und Abrufen der Datensatzliste gemäß column_visible Feld inpublic.fields Tabelle.

Es gibt keine direkte Möglichkeit, eine willkürliche Auswahl von Spalten (Rückgabetyp zum Zeitpunkt des Aufrufs nicht bekannt) von einer Funktion zurückzugeben - oder beliebig SQL-Befehl. SQL fordert zum Zeitpunkt des Aufrufs die Kenntnis von Nummer, Namen und Typen der resultierenden Spalten. Mehr im 2. Kapitel dieser verwandten Antwort:

  • Wie erzeuge ich einen pivotierten CROSS JOIN, bei dem die resultierende Tabellendefinition unbekannt ist?

Es gibt verschiedene Workarounds . Sie könnten das Ergebnis in einen der Standarddokumenttypen (json , jsonb , hstore , xml ).

Oder Sie generieren die Abfrage mit einem Funktionsaufruf und führen das Ergebnis mit dem nächsten aus:

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;

Aufruf:

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

Dies erstellt eine Abfrage der Form:

SELECT usr_id, usr FROM public.users;

Führen Sie es im 2. Schritt aus. (Möglicherweise möchten Sie Spaltennummern hinzufügen und Spalten anordnen.)
Oder \gexec anhängen in psql, um den Rückgabewert sofort auszuführen. Siehe:

So erzwingen Sie die Auswertung einer Unterabfrage, bevor Sie sich einem fremden Server anschließen/herunterdrücken

Schützen Sie sich unbedingt vor SQL-Injection:

  • INSERT mit dynamischem Tabellennamen in Triggerfunktion
  • Tabellen- und Spaltennamen als Argumente in einer plpgsql-Funktion definieren?
Abgesehen davon

varchar(100) macht für Bezeichner, die in Standard-Postgres auf 63 Zeichen begrenzt sind, nicht viel Sinn:

  • Maximale Zeichenanzahl in Beschriftungen (Tabellennamen, Spalten usw.)

Wenn Sie verstehen, wie der Objektidentifizierer regclass eingibt funktioniert, können Sie den Schema- und Tabellennamen durch eine einzelne regclass ersetzen Spalte.