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

Renvoie les lignes correspondant aux éléments du tableau d'entrée dans la fonction plpgsql

Cela fonctionne :

CREATE OR REPLACE FUNCTION avg_purchases(last_names text[] = '{}')
  RETURNS TABLE(last_name text, avg_purchase_size float8) AS
$func$
   SELECT last_name, AVG(purchase_size)::float8
   FROM   purchases
   WHERE  last_name = ANY($1)
   GROUP  BY last_name
$func$  LANGUAGE sql;

Appel :

SELECT * FROM avg_purchases('{foo,Bar,baz,"}weird_name''$$"}');

Ou (mise à jour - exemple avec guillemets en dollars) :

SELECT * FROM avg_purchases($x${foo,Bar,baz,"}weird_name'$$"}$x$);
  • En savoir plus sur la façon de citer des littéraux de chaîne :
    Insérez du texte avec des guillemets simples dans PostgreSQL

  • Vous n'avez pas besoin de SQL dynamique ici.

  • Pendant que vous pouvez enveloppez-le dans une fonction plpgsql (ce qui peut être utile), une simple fonction SQL fait très bien le travail.

  • Vous avez des incompatibilités de type .

    • le résultat de avg() peut être numeric pour tenir un résultat précis. Je lance en float8 pour le faire fonctionner, qui est juste un alias pour double precision (vous pouvez utiliser l'un ou l'autre). Si vous avez besoin d'une précision parfaite, utilisez numeric à la place.
    • Depuis que vous GROUP BY last_name vous voulez un text brut Paramètre OUT au lieu de text[] .

VARIADIC

Un tableau est un type d'entrée utile. Si c'est plus facile pour votre client, vous pouvez également utiliser un VARIADIC paramètre d'entrée qui permet de passer le tableau sous la forme d'une liste d'éléments :

CREATE OR REPLACE FUNCTION avg_purchases(VARIADIC last_names text[] = '{}')
  RETURNS TABLE(last_name text, avg_purchase_size float8) AS
$func$
   SELECT last_name, AVG(purchase_size)::float8
   FROM   purchases
   JOIN  (SELECT unnest($1)) t(last_name) USING (last_name)
   GROUP  BY last_name
$func$  LANGUAGE sql;

Appel :

SELECT * FROM avg_purchases('foo', 'Bar', 'baz', '"}weird_name''$$"}');

Ou (avec guillemets en dollars) :

SELECT * FROM avg_purchases('foo', 'Bar', 'baz', $y$'"}weird_name'$$"}$y$);

Sachez que Postgres standard n'autorise qu'un maximum de 100 éléments . Ceci est déterminé au moment de la compilation par l'option prédéfinie :

max_function_args (integer)

Indique le nombre maximal d'arguments de fonction. Il est déterminé par la valeur de FUNC_MAX_ARGS lors de la construction du serveur. La valeur par défaut est 100 arguments.

Vous pouvez toujours l'appeler avec une notation de tableau lorsqu'il est préfixé avec le mot-clé VARIADIC :

SELECT * FROM avg_purchases(VARIADIC '{1,2,3, ... 99,100,101}');

Pour les tableaux plus grands (plus de 100), j'utiliserais également unnest() dans une sous-requête et JOIN à celui-ci, qui a tendance à mieux s'adapter :

  • Optimiser une requête Postgres avec un grand IN