错误:在无法接受集合的上下文中调用了set_valued函数。什么事啊


11

我在ubuntu 12.04上使用Postgresql 9.1。

克雷格的回答启发,我的问题类型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;

在执行过程中,我得到了错误:

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函数返回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; 将在回答中解释。
Craig Ringer 2013年

@CraigRinger我将分号放回原处。
斯蒂芬·罗兰德

Answers:


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 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;

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


至于问题的后半部分,发生的情况是第一种情况在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-returning函数的方式的区别-在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)

刚刚测试,效果完美。而且,我喜欢这种语法returns table
斯蒂芬·罗兰德

@StephaneRolland也更新了问题后半部分的解释。
Craig Ringer 2013年

thx的支持。现在要清楚得多。
斯蒂芬·罗兰德
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.