Това работи:
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;
Обадете се:
SELECT * FROM avg_purchases('{foo,Bar,baz,"}weird_name''$$"}');
Или (актуализация - пример с цитиране на долари):
SELECT * FROM avg_purchases($x${foo,Bar,baz,"}weird_name'$$"}$x$);
-
Повече за това как да цитирате низови литерали:
Вмъкнете текст с единични кавички в PostgreSQL -
Тук нямате нужда от динамичен SQL.
-
Докато вие можете увийте го във функция plpgsql (която може да е полезна), простата SQL функция върши работата добре.
-
Имате несъответствия на типовете .
- резултатът от
avg()
може да бъдеnumeric
за да има точен резултат. Прехвърлям къмfloat8
за да работи, което е просто псевдоним заdouble precision
(можете да използвате и двете). Ако имате нужда от перфектна прецизност, използвайтеnumeric
вместо това. - Тъй като
GROUP BY last_name
искате обикновенtext
OUT параметър вместоtext[]
.
- резултатът от
VARIADIC
Масивът е полезен тип вход. Ако е по-лесно за вашия клиент, можете да използвате и VARIADIC
входен параметър, който позволява да се предаде масивът като списък с елементи :
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;
Обадете се:
SELECT * FROM avg_purchases('foo', 'Bar', 'baz', '"}weird_name''$$"}');
Или (с цитиране на долари):
SELECT * FROM avg_purchases('foo', 'Bar', 'baz', $y$'"}weird_name'$$"}$y$);
Имайте предвид, че стандартният Postgres позволява само максимум 100 елемента . Това се определя по време на компилиране от предварително зададената опция:
max_function_args (integer)
Отчита максималния брой аргументи на функцията. Определя се от стойността на
FUNC_MAX_ARGS
при изграждане на сървъра. Стойността по подразбиране е 100 аргумента.
Все още можете да го извикате с нотация на масив, когато има префикс с ключовата дума VARIADIC
:
SELECT * FROM avg_purchases(VARIADIC '{1,2,3, ... 99,100,101}');
За по-големи масиви (100+) бих използвал и unnest()
в подзаявка и JOIN
към него, което има тенденция да се мащабира по-добре:
- Оптимизиране на заявка в Postgres с голям IN