Toto funguje:
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;
Volejte:
SELECT * FROM avg_purchases('{foo,Bar,baz,"}weird_name''$$"}');
Nebo (aktualizace – příklad s uvedením dolaru):
SELECT * FROM avg_purchases($x${foo,Bar,baz,"}weird_name'$$"}$x$);
-
Více o tom, jak citovat řetězcové literály:
Vložit text s jednoduchými uvozovkami v PostgreSQL -
Zde nepotřebujete dynamické SQL.
-
Zatímco můžete zabalte to do funkce plpgsql (což může být užitečné), jednoduchá funkce SQL to dělá dobře.
-
Máte neshody typu .
- výsledek
avg()může býtnumericudržet přesný výsledek. Odesílám dofloat8aby to fungovalo, což je jen alias prodouble precision(můžete použít obojí). Pokud potřebujete dokonalou přesnost, použijtenumericmísto toho. - Vzhledem k tomu, že
GROUP BY last_namechcete prostýtextParametr OUT namístotext[].
- výsledek
VARIADIC
Pole je užitečný typ vstupu. Pokud je to pro vašeho klienta jednodušší, můžete také použít VARIADIC vstupní parametr, který umožňuje předat pole jako seznam prvků :
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;
Volejte:
SELECT * FROM avg_purchases('foo', 'Bar', 'baz', '"}weird_name''$$"}');
Nebo (s dolarem):
SELECT * FROM avg_purchases('foo', 'Bar', 'baz', $y$'"}weird_name'$$"}$y$);
Uvědomte si, že standardní Postgres povoluje pouze maximálně 100 prvků . To je určeno v době kompilace přednastavenou možností:
max_function_args (integer)Hlásí maximální počet argumentů funkce. Je určena hodnotou
FUNC_MAX_ARGSpři stavbě serveru. Výchozí hodnota je 100 argumentů.
Stále jej můžete volat pomocí zápisu pole, když je předponou klíčové slovo VARIADIC :
SELECT * FROM avg_purchases(VARIADIC '{1,2,3, ... 99,100,101}');
Pro větší pole (100+) bych také použil unnest() v dílčím dotazu a JOIN k tomu, který má tendenci se lépe škálovat:
- Optimalizace dotazu Postgres s velkým IN