Това работи:
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искате обикновенtextOUT параметър вместо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