Я использую Postgresql 9.1, с Ubuntu 12.04.
Вдохновленный ответ Крейга на мой вопрос Конкатенацию setof типа или setof записи , я думал , я бы хорошо с использованием return query
, setof record
и генератор серии в этой функцию plpgsql:
create or replace function compute_all_pair_by_craig(id_obj bigint)
returns setof record as $$
begin
return query select o.id, generate_series(0,o.value) from m_obj as o;
end;
$$ language plpgsql;
Во время выполнения я получаю ошибку:
ERROR: set_valued function called in context that cannot accept a set
Что не так ? В отличие от Крейга, я говорю, чтобы функция возвращалась setof record
.
Я могу добиться чего-то, что работает точно так же, как Крейг, то есть определив тип, create type pair_id_value as (idx bigint, value integer)
и моя функция plpgsql возвращает a setof of pair_id_value
вместо a setof record
.
Но даже с этим рабочим решением я все еще не понимаю, почему select id, generate_series(0,13)
один вернет результат в двух столбцах ... и, наоборот, вызов функции (возвращает setof pair_id_value) return query select id, generate_series(0,my_obj.value) from my_obj
вернет результат только в одном столбце, поле которого выглядит как это "(123123,0)" "(123123,1)" "(123123,2)" (3 строки), которые, очевидно, являются кортежами.
Это тот случай, когда временная таблица должна быть создана?
источник
BEGIN
и пропущенная послеRETURN QUERY
. После исправления этих ошибок я подтверждаю ошибку при возвратеrecord
; объясню в ответ.Ответы:
Сообщение об ошибке не очень полезно:
но если вы перефразируете запрос, чтобы вызвать его как правильную функцию, возвращающую множество, вы увидите настоящую проблему:
Если вы используете
SETOF RECORD
безOUT
списка параметров, вы должны указать результаты в операторе вызова, например:Тем не менее, гораздо лучше использовать
RETURNS TABLE
илиOUT
параметры. С прежним синтаксисом ваша функция будет:Это можно вызвать в контексте списка SELECT и можно использовать без явного создания типа или указания структуры результата на сайте вызова.
Что касается второй половины вопроса, то, что происходит, это то, что 1-й случай задает два отдельных столбца в SELECT-списке, тогда как второй возвращает один составной. На самом деле это не связано с тем, как вы возвращаете результат, а с тем, как вы вызываете функцию. Если мы создаем образец функции:
Вы увидите разницу в двух способах вызова функции, возвращающей множество - в
SELECT
списке нестандартное расширение для PostgreSQL со странным поведением:или в виде таблицы более стандартным способом:
источник
returns table
.