PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Passer plusieurs ensembles ou tableaux de valeurs à une fonction

Vous pouvez y parvenir avec une simple fonction SQL. La fonctionnalité clé est la fonction 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;

Appel :

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

Ou la même chose avec un tableau littéral - ce qui est plus pratique dans certains contextes, notamment avec des instructions préparées :

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

La fonction toujours attend un tableau 2D. Même si vous passez une seule paire, imbriquez-la :

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

Audit de votre implémentation

  1. Vous avez créé la fonction VOLATILE , mais il peut être STABLE . Par documentation :

    En raison de ce comportement d'instantané, une fonction contenant uniquement SELECT les commandes peuvent être marquées en toute sécurité STABLE .

    Connexe :

    • Comment passer un paramètre dans une fonction de date
  2. Vous utilisez également LANGUAGE plpgsql au lieu de sql , ce qui est logique si vous exécutez la fonction plusieurs fois dans la même session. Mais alors vous devez aussi le rendre STABLE ou vous perdez cet avantage potentiel en termes de performances. Le manuel une fois de plus :

    STABLE et IMMUTABLE les fonctions utilisent un instantané établi au début de la requête appelante, tandis que les fonctions VOLATILES obtiennent un nouvel instantané au début de chaque requête qu'elles exécutent.

  3. Votre EXPLAIN la sortie affiche une analyse d'index uniquement , pas une analyse séquentielle comme vous le soupçonnez dans votre commentaire.

  4. Il y a aussi une étape de tri dans votre EXPLAIN sortie qui ne correspond pas au code que vous affichez. Êtes-vous sûr d'avoir copié le bon EXPLAIN production? Comment l'avez-vous obtenu d'ailleurs ? Les fonctions PL/pgSQL sont des boîtes noires pour EXPLAIN . Avez-vous utilisé auto_explain ? Détails :

    • Plan de requête Postgres d'une invocation UDF écrite en pgpsql
  5. Le planificateur de requête Postgres n'a aucune idée du nombre d'éléments de tableau que le paramètre passé aura, il est donc difficile de planifier la requête et il peut s'agir par défaut d'une analyse séquentielle (en fonction de plusieurs facteurs). Vous pouvez aider en déclarant le nombre de lignes attendu. Si vous n'avez généralement pas plus de 10 éléments, ajoutez ROWS 10 comme je l'ai fait maintenant ci-dessus. Et testez à nouveau.