Ошибка синтаксиса в процессе создания агрегированных
Попытка создать агрегатную функцию:
create aggregate min (my_type) (
sfunc = least,
stype = my_type
);
ERROR: syntax error at or near "least"
LINE 2: sfunc = least,
^
Что я упускаю?
Хотя руководство вызывает least
функцию:
Наибольшая и наименьшая функции выбирают наибольшее или наименьшее значение из списка любого числа выражений.
Я не могу его найти:
dfS least
List of functions
Schema | Name | Result data type | Argument data types | Type
--------+------+------------------+---------------------+------
(0 rows)
2 ответа:
LEAST
иGREATEST
не являются реальными функциями; внутренне они разбираются какMinMaxExpr
(см.src/include/nodes/primnodes.h
).Вы можете достичь желаемого с помощью такой универсальной функции:
CREATE FUNCTION my_least(anyelement, anyelement) RETURNS anyelement LANGUAGE sql IMMUTABLE CALLED ON NULL INPUT AS 'SELECT LEAST($1, $2)';
(Спасибо Эрвину Брандштеттеру за
CALLED ON NULL INPUT
и идею использоватьLEAST
.)Тогда вы можете создать свой агрегат как
CREATE AGGREGATE min(my_type) (sfunc = my_least, stype = my_type);
Это будет работать только в том случае, если существуют функции сравнения для
my_type
, в противном случае вам придется придумать другую функциюmy_least
.
Как
CASE
,COALESCE
и ещеNULLIF
,GREATEST
иLEAST
перечислены в главе условные выражения. Эти конструкции SQL не реализуются как функции .. как @Laurenz обеспечил в то же время.Руководство советует:
Совет: Если ваши потребности выходят за рамки возможностей этих условных выражения, вы можете рассмотреть возможность записи хранимой процедуры в более выразительное Программирование язык.
Терминология здесь тоже немного не та, поскольку Postgres не поддерживает истинные "хранимые процедуры", а только функции. (Именно поэтому существуетоткрытый пункт TODO "реализация хранимых процедур".)
Эту страницу руководства можно было бы заострить, чтобы избежать путаницы ...
@Laurenz также привел пример. Я бы просто использовал
LEAST
в функции, чтобы получить идентичную функциональность:CREATE FUNCTION f_least(anyelement, anyelement) RETURNS anyelement LANGUAGE sql IMMUTABLE AS 'SELECT LEAST($1, $2)';
Do нет сделайте это
STRICT
, чтобы это было бы неверно.LEAST(1, NULL)
возвращает1
, а неNULL
.Даже если бы
Обратите внимание, что эта функция ограничена ровно двумя параметрами, в то время какSTRICT
был правильным, я бы не стал его использовать, потому что он может предотвратить подстановку функций.LEAST
принимает любое число параметров. Вы можете перегрузить функцию, чтобы покрыть 3, 4 и т. д. входной параметр. Или вы можете написать функциюVARIADIC
Для 100 параметров.