如何在PL / pgSQL中正确使用`RETURN NEXT`?

时间:2014-12-27 00:04:12

标签: postgresql plpgsql

我正在尝试使用返回表的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;

3 个答案:

答案 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)

@Craig already explained

加号,如果你真的需要一个循环,你可以更简单/更便宜。您不需要声明其他记录变量并重复分配。在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)相同。