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

Gibt SETOF-Zeilen von der PostgreSQL-Funktion zurück

Bereinigungsfunktion

Was Sie derzeit haben, kann vereinfacht / bereinigt werden zu:

CREATE OR REPLACE FUNCTION func_a (username text = '', databaseobject text = '')
  RETURNS ????
  LANGUAGE plpgsql AS
$func$
BEGIN
   RETURN QUERY EXECUTE
   format ('SELECT * FROM %s v1 LEFT JOIN %I v2 USING (id)'
         , CASE WHEN username = '*' THEN 'view1' ELSE 'view3' END
         , databaseobject);
END
$func$;

Sie brauchen nur zusätzliche Instanzen von BEGIN ... END im Funktionskörper, um separate Codeblöcke mit ihrem eigenen Gültigkeitsbereich zu starten, was selten benötigt wird.

Der Standard-SQL-Verkettungsoperator ist || . + ist eine "kreative" Ergänzung Ihres ehemaligen Anbieters.

Verwenden Sie keine CaMeL-Fallbezeichner, es sei denn, Sie setzen sie in doppelte Anführungszeichen. Verwenden Sie sie am besten gar nicht. Siehe:

  • Beachten Sie bei PostgreSQL-Spaltennamen die Groß-/Kleinschreibung?

varchar(4000) ist auch auf eine bestimmte Einschränkung von SQL Server zugeschnitten. Es hat keine besondere Bedeutung in Postgres. Verwenden Sie nur varchar(4000) wenn Sie tatsächlich ein Limit von 4000 Zeichen benötigen. Ich würde einfach text verwenden - außer dass wir überhaupt keine Variablen brauchen hier, nach Vereinfachung der Funktion.

Wenn Sie format() nicht verwendet haben , konsultieren Sie jedoch das Handbuch hier.

Rückgabetyp

Nun zu Ihrer eigentlichen Frage:Der Rückgabetyp für eine dynamische Abfrage kann schwierig sein, da SQL verlangt, dass dieser spätestens zum Zeitpunkt des Aufrufs deklariert wird. Wenn Sie eine Tabelle oder Ansicht oder einen zusammengesetzten Typ in Ihrer Datenbank haben, die bereits mit der Spaltendefinitionsliste übereinstimmen, können Sie einfach Folgendes verwenden:

CREATE FUNCTION foo()
  RETURNS SETOF my_view AS
...

Andernfalls buchstabieren Sie die Spaltendefinitionsliste ohne out mit (am einfachsten) RETURNS TABLE :

CREATE FUNCTION foo()
  RETURNS TABLE (col1 int, col2 text, ...) AS
...

Wenn Sie den Zeilentyp im Laufe der Zeit anpassen, können Sie anonyme Datensätze zurückgeben:

CREATE FUNCTION foo()
  RETURNS SETOF record AS
...

Aber dann muss man bei jedem Aufruf eine Spaltendefinitionsliste angeben, also benutze ich das kaum.

Ich würde SELECT * nicht verwenden zunächst. Verwenden Sie eine endgültige Liste der zurückzugebenden Spalten und deklarieren Sie Ihren Rückgabetyp entsprechend:

CREATE OR REPLACE FUNCTION func_a(username text = '', databaseobject text = '')
  RETURNS TABLE(col1 int, col2 text, col3 date)
  LANGUAGE plpgsql AS
$func$
BEGIN
   RETURN QUERY EXECUTE
   format ($f$SELECT v1.col1, v1.col2, v2.col3
              FROM %s v1 LEFT JOIN %I v2 USING (id)$f$
         , CASE WHEN username = '*' THEN 'view1' ELSE 'view3' END
         , databaseobject);
END
$func$;

Erwägen Sie für vollständig dynamische Abfragen, die Abfrage zunächst in Ihrem Client zu erstellen, anstatt eine Funktion zu verwenden.

Sie müssen zuerst die Grundlagen verstehen:

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

Dann gibt es erweiterte Optionen mit polymorphen Typen, die es Ihnen ermöglichen, den Rückgabetyp zum Zeitpunkt des Aufrufs zu übergeben. Mehr im letzten Kapitel von:

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