Ошибка: функция set_valued, вызываемая в контексте, которая не может принять набор. О чем это?

Я использую 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 возвращает setof of pair_id_value вместо setof record.

Но даже с этим рабочим решением я все еще не понимаю, почему только select id, generate_series(0,13) вернет результат в два столбца ... и, наоборот, вызов функции (возвращает setof пары_id_value) с помощью return query select id, generate_series(0,my_obj.value) from my_obj вернет результат в только один столбец , который выглядит так: «(123123,0)» «(123123,1)» «(123123,2)» (3 строки), которые, очевидно, являются кортежами.

Это случай, когда временная таблица должна /должна быть создана?

11 голосов | спросил Stephane Rolland 26 MarpmTue, 26 Mar 2013 15:29:38 +04002013-03-26T15:29:38+04:0003 2013, 15:29:38

1 ответ


7

Сообщение об ошибке не очень полезно:

regress=> SELECT * FROM  compute_all_pair_by_craig(100);
ERROR:  a column definition list is required for functions returning "record"
LINE 1: SELECT * FROM  compute_all_pair_by_craig(100);

, но если вы перефразируете запрос, чтобы называть его правильной функцией возврата к набору, вы увидите реальную проблему:

regress=> SELECT * FROM compute_all_pair_by_craig(100);
ERROR:  a column definition list is required for functions returning "record"
LINE 1: SELECT * FROM compute_all_pair_by_craig(100);

Если вы используете SETOF RECORD без OUT, вы должны указать результаты в вызывающем операторе, например:

regress=> SELECT * FROM compute_all_pair_by_craig(100) theresult(a integer, b integer);

Однако гораздо лучше использовать RETURNS TABLE или OUT. С прежним синтаксисом ваша функция будет:

create or replace function compute_all_pair_by_craig(id_obj bigint)
    returns table(a integer, b integer) as $$
begin
    return query select o.id, generate_series(0,o.value) from m_obj as o;     
end;
$$ language plpgsql;

Это может быть вызвано в контексте SELECT-списка и может использоваться без явного указания типа или указания структуры результата на сайте вызова.


Что касается второй половины вопроса, то происходит то, что 1-й случай указывает два отдельных столбца в SELECT-списке, а второй возвращает один составной. На самом деле это не связано с тем, как вы возвращаете результат, но как вы вызываете эту функцию. Если мы создадим образецную функцию:

CREATE OR REPLACE FUNCTION twocols() RETURNS TABLE(a integer, b integer) 
AS $$ SELECT x, x FROM generate_series(1,5) x; $$ LANGUAGE sql;

Вы увидите разницу в двух способах вызова функции set-return - в списке SELECT, специфичном для PostgreSQL нестандартное расширение с причудливым поведением:

regress=> SELECT twocols();
 twocols 
---------
 (1,1)
 (2,2)
 (3,3)
 (4,4)
 (5,5)
(5 rows)

или как таблица более стандартным образом:

regress=> SELECT * FROM twocols();
 a | b 
---+---
 1 | 1
 2 | 2
 3 | 3
 4 | 4
 5 | 5
(5 rows)
ответил Craig Ringer 26 MarpmTue, 26 Mar 2013 15:37:28 +04002013-03-26T15:37:28+04:0003 2013, 15:37:28

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132