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 êtrenumeric
pour tenir un résultat précis. Je lance enfloat8
pour le faire fonctionner, qui est juste un alias pourdouble precision
(vous pouvez utiliser l'un ou l'autre). Si vous avez besoin d'une précision parfaite, utiliseznumeric
à la place. - Depuis que vous
GROUP BY last_name
vous voulez untext
brut Paramètre OUT au lieu detext[]
.
- le résultat de
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