错误:在不能接受集合的上下文中调用 set_valued 函数。它是关于什么的?

Ste*_*and 11 postgresql stored-procedures plpgsql set-returning-functions

我使用 Postgresql 9.1 和 ubuntu 12.04。

克雷格的回答启发,我的问题类型SETOF或SETOF纪录的级联我以为我会使用顺利return querysetof 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;
Run Code Online (Sandbox Code Playgroud)

在执行期间我收到错误:

ERROR: set_valued function called in context that cannot accept a set

怎么了 ?与 Craig 相反,我告诉函数返回setof record

我可以实现与 Craig 完全一样的工作,即通过定义类型create type pair_id_value as (idx bigint, value integer)并让我的 plpgsql 函数返回 asetof of pair_id_value而不是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行)显然是元组。

是否必须/应该创建临时表?

Cra*_*ger 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);
Run Code Online (Sandbox Code Playgroud)

但是,如果您将查询改写为一个适当的集合返回函数,您将看到真正的问题:

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);
Run Code Online (Sandbox Code Playgroud)

如果您在SETOF RECORD没有OUT参数列表的情况下使用,则必须在调用语句中指定结果,例如:

regress=> SELECT * FROM compute_all_pair_by_craig(100) theresult(a integer, b integer);
Run Code Online (Sandbox Code Playgroud)

但是,使用RETURNS TABLEOUT参数要好得多。使用前一种语法,您的函数将是:

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;
Run Code Online (Sandbox Code Playgroud)

这在 SELECT-list 上下文中是可调用的,并且可以在不显式创建类型或在调用站点指定结果结构的情况下使用。


至于问题的后半部分,发生的情况是第一种情况在 SELECT 列表中指定了两个单独的列,而第二种情况返回单个组合。这实际上与返回结果的方式无关,而是与调用函数的方式有关。如果我们创建示例函数:

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

您将看到调用 set-returning 函数的两种方法的区别 - 在SELECT列表中,具有古怪行为的 PostgreSQL 特定非标准扩展:

regress=> SELECT twocols();
 twocols 
---------
 (1,1)
 (2,2)
 (3,3)
 (4,4)
 (5,5)
(5 rows)
Run Code Online (Sandbox Code Playgroud)

或者以更标准的方式作为表格:

regress=> SELECT * FROM twocols();
 a | b 
---+---
 1 | 1
 2 | 2
 3 | 3
 4 | 4
 5 | 5
(5 rows)
Run Code Online (Sandbox Code Playgroud)