我正在尝试使用返回表的PL / pgSQL(PostgreSQL 9.3)函数编写循环。我在循环中的每个查询之后使用RETURN NEXT;
没有参数,后面的示例如plpgsql error "RETURN NEXT cannot have a parameter in function with OUT parameters" in table-returning function和其他地方。但是,我仍然收到一条错误消息:
ERROR: query has no destination for result data
HINT: If you want to discard the results of a SELECT, use PERFORM instead.
重现问题的最小代码示例如下。任何人都可以帮助解释如何修复测试代码以返回表格吗?
提前致谢。
最小例子:
CREATE OR REPLACE FUNCTION test0()
RETURNS TABLE(y integer, result text) AS $func$
DECLARE
yr RECORD;
BEGIN
FOR yr IN SELECT * FROM generate_series(1,10,1) AS y_(y)
LOOP
RAISE NOTICE 'Computing %', yr.y;
SELECT yr.y, 'hi';
RETURN NEXT;
END LOOP;
RETURN;
END
$func$ LANGUAGE plpgsql;
答案 0 :(得分:7)
给出的示例可以完全替换为RETURN QUERY
:
BEGIN
RETURN QUERY SELECT y_.y, 'hi' FROM generate_series(1,10,1) AS y_(y)
END;
这将是 lot 更快。
一般情况下,你应该尽可能避免迭代,而是支持面向集合的操作。
循环上的return next
是不可避免的(这是非常罕见的,并且主要局限于需要异常处理时),您必须设置OUT
参数值或表参数,然后return next
没有争论。
在这种情况下,您的问题是行SELECT yr.y, 'hi';
,它什么都不做。您假设SELECT
的隐含目标是out参数,但事实并非如此。您必须使用out参数作为循环变量,如@peterm,使用赋值或使用SELECT INTO
:
FOR yr IN SELECT * FROM generate_series(1,10,1) AS y_(y)
LOOP
RAISE NOTICE 'Computing %', yr.y;
y := yr.y;
result := 'hi';
RETURN NEXT;
END LOOP;
RETURN;
答案 1 :(得分:3)
一种方法
CREATE OR REPLACE FUNCTION test0()
RETURNS TABLE(y integer, result text) AS $$
BEGIN
FOR y, result IN
SELECT s.y, 'hi' result FROM generate_series(1,10,1) AS s(y)
LOOP
RETURN NEXT;
END LOOP;
END
$$ LANGUAGE plpgsql;
SELECT * FROM test0();
结果:
| Y | RESULT | |----|--------| | 1 | hi | | 2 | hi | | 3 | hi | | 4 | hi | | 5 | hi | | 6 | hi | | 7 | hi | | 8 | hi | | 9 | hi | | 10 | hi |
这是 SQLFiddle 演示
答案 2 :(得分:1)
加号,如果你真的需要一个循环,你可以更简单/更便宜。您不需要声明其他记录变量并重复分配。在plpgsql中,赋值相对较高。直接分配到OUT
中声明的RETURNS TABLE
变量。这些在代码中随处可见,FOR
循环也可以分配给变量列表。 Per documentation:
目标 是记录变量,行变量或逗号分隔的标量变量列表。
CREATE OR REPLACE FUNCTION test0()
RETURNS TABLE(y integer, result text) AS
$func$
DECLARE
yr RECORD;
BEGIN
FOR y, result IN
SELECT g, 'text_'::text || g
FROM generate_series(1,10) g
LOOP
RAISE NOTICE 'Computing %', y;
RETURN NEXT;
END LOOP;
END
$func$ LANGUAGE plpgsql;
不 使用标识符y
两次(作为OUT
param和列别名),同时您可以轻松避免使用。那是一个装满脚的枪。有时无法避免这种情况,在这种情况下始终使用表限定列。
没有参数的最终RETURN
是好的形式,但完全是可选的。当控件到达最终END
时,将自动返回完整的结果。
g
中的{li> FROM generate_series(1,10) g
会自动表别名和列别名。它实际上与FROM generate_series(1,10) g(g)
相同。