Я пытаюсь создать в PostgreSQL функцию, которая бы принимала имя таблицы и имя одного столбца в этой таблице (в varchars); и вернуть массив, который будет иметь минимальные и максимальные значения этого столбца.
Заранее я не (не хочу) знать тип столбца, т.е. тип элементов в возвращаемом массиве.
Я пытался создать функцию с полиморфным произвольным массивом в качестве возвращаемого типа, но продолжаю использовать синтаксические ошибки. Пробовал как в SQL, так и в PLPQSQL.
CREATE OR REPLACE FUNCTION minmax(tablename character varying, columnname character varying, OUT minmaxa anyarray) AS
$function$
BEGIN
EXECUTE FORMAT('SELECT array_agg(foo) AS %s FROM (
(SELECT min(%s) AS foo FROM %s)
UNION
(SELECT max(%s) AS foo FROM %s)
) AS foobar'
, columnname
, columnname, tablename
, columnname, tablename)
INTO minmaxa;
END
$function$
LANGUAGE plpgsql;
Строка из ФОРМАТА будет:
SELECT array_agg(foo) AS columnname FROM (
(SELECT min(columnname) AS foo FROM tablename)
UNION
(SELECT max(columnname) AS foo FROM tablename)
) AS foobar
Тогда контрольный пример:
create table example (columnA int, columnB varchar);
insert into example (columnA, columnB) values (1, 'ac'), (2, 'ab'), (3, 'aa');
select minmax('example', 'columnA');
select minmax('example', 'columnB');
select array_agg(columnA) from (
(select min(columnA) AS columnA from example)
UNION
(select max(columnA) AS columnA from example)
) AS foobar;
Должен вернуться:
{1,3}
{ 'Аа', 'ас'}
{1,3}
Но в настоящее время определение функции дает:
«Ошибка SQL [42P13]: ОШИБКА: невозможно определить тип данных результата
Подробно: функция, возвращающая полиморфный тип, должна иметь хотя бы один полиморфный аргумент. "
Я могу заставить его работать, определив фиктивный параметр функции 'foo':
CREATE OR REPLACE FUNCTION minmax(tablename character varying, columnname character varying, foo anyelement, OUT minmaxa anyarray)
(Примечание. Параметр функции foo нигде не используется в теле функции.)
А теперь даем фиктивное значение правильного типа возвращаемого массива при вызове функции:
select minmax('example', 'columnB', ''::varchar);
select minmax('example', 'columnA', 0::int);
Тогда это работает, но что нужно изменить, чтобы мне не понадобился этот фиктивный параметр функции?