在表返回函数中,plpgsql错误“RETURN NEXT在OUT参数的函数中没有参数”

时间:2012-12-26 11:06:49

标签: postgresql exception-handling plpgsql

我在PostgreSQL 9.2中有一个plpgsql函数,它返回一个表。该函数运行几个SELECT,返回与函数相同的列,然后返回这些结果或引发异常,具体取决于某些检查。我可以看到这样做的唯一方法是使用FOR ... LOOP,但我无法找到一种方便的方法来返回行。

我想做这样的事情:

CREATE OR REPLACE FUNCTION my_function()
RETURNS TABLE(column1 integer, column2 boolean, ...)
AS $BODY$
DECLARE
    result_row RECORD;
BEGIN
    FOR result_row IN (SELECT * FROM other_function_returning_same_columns()) LOOP
        IF something_wrong_with(result_row) THEN
            RAISE EXCEPTION 'Something went wrong';
        END IF;

        RETURN NEXT result_row;
    END LOOP;
END
$BODY$ LANGUAGE plpgsql STABLE;

这给了我一个错误:

  

错误:RETURN NEXT在OUT参数的功能中无法使用参数

我不确定为什么Postgres在这里抱怨,因为我的代码看起来很像documentation中的示例,除了我的函数返回TABLE而不是SETOF。没有OUT参数。

我最终设法使用

让它工作
RETURN QUERY SELECT result_row.column1, result_row.column2, ...;

但是必须一直列出所有列是丑陋的,难以维护。我相信一定有更好的方法。

1 个答案:

答案 0 :(得分:21)

RETURN NEXT只返回RETURNS子句(column1, column2, ..)中声明的参数。您无法为此表单提供参数。

  

没有OUT参数。

RETURNS TABLE(column1 integer, column2 boolean, ...)中声明的参数与OUT参数实际上相同

这应该这样做:

CREATE OR REPLACE FUNCTION my_function()
  RETURNS TABLE(column1 integer, column2 boolean, ...) AS
$BODY$
BEGIN
   FOR column1, column2, ... IN 
      SELECT * FROM other_function_returning_same_columns()
   LOOP
      IF something_wrong_with(column1, column2, ...) THEN
         RAISE EXCEPTION 'Something went wrong';
      END IF;

      RETURN NEXT;
    END LOOP;
END
$BODY$ LANGUAGE plpgsql STABLE;

使用注册类型

更简单

您可以使用已注册的复合类型进一步简化:

CREATE TYPE mytype (column1 integer, column2 boolean, ...);

或者,如果您的类型恰好与表定义匹配,那么您已经拥有该类型,因为每个表名都可以用作PostgreSQL中的类型名。然后简化:

CREATE OR REPLACE FUNCTION my_function()
  RETURNS SETOF mytype LANGUAGE plpgsql STABLE AS
$func$
DECLARE
   _r mytype;
BEGIN
   FOR _r IN 
     SELECT * FROM other_function_returning_same_columns()
   LOOP
      IF something_wrong_with(_r) THEN
         RAISE EXCEPTION 'Something went wrong';
      END IF;

      RETURN NEXT _r;
   END LOOP;
END
$func$;

改组!

我很确定所有这些都可以更有效地组织更多

如果您将RAISE命令集成到辅助函数something_wrong_with()中并更方便地命名它(或者它是邪恶的双胞胎)everything_groovy(),那么您可以完全替换my_function()这个简单的查询:

SELECT *
FROM   other_function_returning_same_columns() f
WHERE  everything_groovy(f);

或者将RAISE集成到基函数other_function_returning_same_columns()中以进一步简化(并使其更快)。如果您在某些情况下只想RAISE EXCEPTION,则可以随时添加一个参数(默认值)来打开/关闭它。