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

Passa più set o matrici di valori a una funzione

Puoi ottenerlo con una semplice funzione SQL. La caratteristica fondamentale è la funzione 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;

Chiama:

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

O lo stesso con un array letterale - che è più conveniente in alcuni contesti, soprattutto con dichiarazioni preparate:

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

La funzione sempre si aspetta un array 2D. Anche se passi una singola coppia, nidificala:

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

Verifica della tua implementazione

  1. Hai creato la funzione VOLATILE , ma può essere STABLE . Per documentazione:

    A causa di questo comportamento di snapshot, una funzione contenente solo SELECT i comandi possono essere contrassegnati in modo sicuro STABLE .

    Correlati:

    • Come passare un parametro in una funzione data
  2. Usi anche LANGUAGE plpgsql invece di sql , che ha senso se si esegue la funzione più volte nella stessa sessione. Ma poi devi anche renderlo STABLE o perdi quel potenziale vantaggio in termini di prestazioni. Il manuale ancora una volta:

    STABLE e IMMUTABLE le funzioni utilizzano uno snapshot stabilito all'inizio della query chiamante, mentre le funzioni VOLATILE ottengono un nuovo snapshot all'inizio di ogni query che eseguono.

  3. Il tuo EXPLAIN l'output mostra una Scansione solo indice , non una scansione sequenziale come sospetti nel tuo commento.

  4. C'è anche un passaggio di ordinamento nel tuo EXPLAIN output che non corrisponde al codice mostrato. Sei sicuro di aver copiato il EXPLAIN corretto produzione? Come l'hai ottenuto comunque? Le funzioni PL/pgSQL sono scatole nere per EXPLAIN . Hai usato auto_explain ? Dettagli:

    • Piano di query Postgres di una chiamata UDF scritta in pgpsql
  5. Il pianificatore di query di Postgres non ha idea di quanti elementi dell'array avrà il parametro passato, quindi è difficile pianificare la query e potrebbe utilizzare per impostazione predefinita una scansione sequenziale (a seconda di più fattori). Puoi aiutare dichiarando il numero previsto di righe. Se in genere non hai più di 10 articoli aggiungi ROWS 10 come ho fatto ora sopra. E prova ancora.