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

Übergeben Sie mehrere Sätze oder Arrays von Werten an eine Funktion

Das erreichen Sie mit einer einfachen SQL-Funktion. Hauptmerkmal ist die Funktion generate_subscripts() :

CREATE OR REPLACE FUNCTION f_attendance(_arr2d int[])
  RETURNS SETOF attendance AS
$func$
   SELECT a.*
   FROM   generate_subscripts($1, 1) i
   JOIN   attendance a ON a.class   = $1[i][1]
                      AND a.section = $1[i][2]
$func$  LANGUAGE ROWS 10 sql STABLE;

Aufruf:

SELECT * FROM f_attendance(ARRAY[[1,1],[2,2]]);

Oder dasselbe mit einem Array literal - was in manchen Zusammenhängen bequemer ist, besonders bei vorbereiteten Anweisungen:

SELECT * FROM f_attendance('{{1,1},{2,2}}');

Die Funktion immer erwartet ein 2D-Array. Auch wenn Sie ein einzelnes Paar übergeben, verschachteln Sie es:

SELECT * FROM f_attendance('{{1,1}}');

Audit Ihrer Implementierung

  1. Sie haben die Funktion VOLATILE erstellt , aber es kann STABLE sein . Per Dokumentation:

    Aufgrund dieses Snapshot-Verhaltens enthält eine Funktion nur SELECT Befehle können bedenkenlos mit STABLE gekennzeichnet werden .

    Verwandte:

    • Wie man einen Parameter an eine Datumsfunktion übergibt
  2. Sie verwenden auch LANGUAGE plpgsql statt sql , was sinnvoll ist, wenn Sie die Funktion mehrmals in derselben Sitzung ausführen. Aber dann müssen Sie es auch STABLE machen oder Sie verlieren diesen potenziellen Leistungsvorteil. Nochmal die Anleitung:

    STABLE und IMMUTABLE Funktionen verwenden einen Snapshot, der zu Beginn der aufrufenden Abfrage erstellt wird, während VOLATILE-Funktionen einen frischen Snapshot am Beginn jeder von ihnen ausgeführten Abfrage erhalten.

  3. Ihr EXPLAIN Ausgabe zeigt einen Index Only Scan , kein sequenzieller Scan, wie Sie in Ihrem Kommentar vermuten.

  4. Es gibt auch einen Sortierschritt in Ihrem EXPLAIN Ausgabe, die nicht mit dem angezeigten Code übereinstimmt. Sind Sie sicher, dass Sie den richtigen EXPLAIN kopiert haben Ausgang? Wie hast du es überhaupt bekommen? PL/pgSQL-Funktionen sind Black Boxes, die EXPLAIN werden müssen . Haben Sie auto_explain verwendet? ? Einzelheiten:

    • Postgres-Abfrageplan eines in pgpsql geschriebenen UDF-Aufrufs
  5. Der Postgres-Abfrageplaner hat keine Ahnung, wie viele Array-Elemente der übergebene Parameter haben wird, daher ist es schwierig, die Abfrage zu planen, und es kann standardmäßig ein sequenzieller Scan verwendet werden (abhängig von weiteren Faktoren). Sie können helfen, indem Sie die erwartete Anzahl von Zeilen angeben. Wenn Sie normalerweise nicht mehr als 10 Elemente haben, fügen Sie ROWS 10 hinzu wie ich es jetzt oben getan habe. Und erneut testen.