从 plpgsql 函数返回行集。

Returning set of rows from plpgsql function.

我想 return table 来自 plpgsql 函数。

这是我的代码。

    CREATE FUNCTION test() RETURNS my_table AS
    $BODY$DECLARE
        q4 my_table;
    BEGIN
        q4 := SELECT * FROM my_table;
        RETURN q4;
    END;$BODY$
    LANGUAGE sql;

我收到以下错误:

    Error: ERROR:  syntax error at or near "SELECT"
    LINE 5:  q4 := SELECT * FROM my_table;

我从这个开始questions/tutorials。 https://dba.stackexchange.com/questions/35721/declare-variable-of-table-type-in-pl-pgsql && http://postgres.cz/wiki/PL/pgSQL_%28en%29

我的想法是我需要将此查询分配给一个变量。这只是我想要创建的功能的一小部分。

第二个问题是如何遍历该集合并进行一些数学运算并为该集合的某些字段赋值 table。 但是首先我想解决这个问题。

CREATE FUNCTION test() 
RETURNS my_table AS
$BODY$
DECLARE
    q4 my_table;
BEGIN
    -- add brackets to get a value 
    -- select row as one value, as q4 is of the type my_table
    -- and limit result to one row
    q4 := (SELECT my_table FROM my_table ORDER BY 1 LIMIT 1);
    RETURN q4;
END;$BODY$
-- change language to plpgsql
LANGUAGE plpgsql;
  • 您不能在 sql 函数中使用变量,请使用 plpgsql.
  • 您可以为变量分配单个值,而 select query returns 行集。
  • 您必须 select 一行作为一个值,因为变量是复合类型。

循环使用示例:

DROP FUNCTION test();
CREATE FUNCTION test() 
-- change to SETOF to return set of rows, not a single row
RETURNS SETOF my_table AS
$BODY$
DECLARE
    q4 my_table;
BEGIN
    FOR q4 in
        SELECT * FROM my_table
    LOOP
        RETURN NEXT q4;
    END LOOP;
END;$BODY$
LANGUAGE plpgsql;

SELECT * FROM test();

阅读有关 Returning From a Function

的文档

PostgreSQL 没有 table 变量。所以你不能通过任何变量 return table 。当您创建任何 table 时,PostgreSQL 会创建具有相同名称的复合类型。但它不是 table 类型 - 它是复合类型 - 记录。

CREATE TABLE xx(a int, b int);

CREATE OR REPLACE FUNCTION foo()
RETURNS xx AS $$
DECLARE v xx;
BEGIN
  v := (10,20);
  RETURN v;
END;
$$ LANGUAGE plpgsql;

函数 foo returns 复合值 - 它不是 table。但是您可以编写一些函数,其中 returns 一组复合值 - 它是 table.

CREATE OR REPLACE FUNCTION foo(a int)
RETURNS SETOF xx AS $$
DECLARE v xx;
BEGIN
  FOR i IN 1..a LOOP
    v.a := i; v.b := i+1;
    RETURN NEXT v;
  END LOOP;
  RETURN;
END;
$$ LANGUAGE plpgsql;

postgres=# SELECT * FROM foo(3);
┌───┬───┐
│ a │ b │
╞═══╪═══╡
│ 1 │ 2 │
│ 2 │ 3 │
│ 3 │ 4 │
└───┴───┘
(3 rows)

当结果基于查询时,可以使用RETURN QUERY。它比 FOR IN SELECTRETURN NEXT:

更快、更短、更易读
CREATE OR REPLACE FUNCTION foo2(a int)
RETURNS SETOF xx AS $$
BEGIN
  RETURN QUERY SELECT * FROM xx
                  WHERE xx.a = foo2.a;
  RETURN;
END;
$$ LANGUAGE plpgsql;

谨慎使用这些功能。它们对于优化器来说是一个黑盒子,所以优化器不能同时优化函数查询和外部查询,它必须分别优化这些查询,这对于一些复杂的查询应该是无效的。如果外部查询简单,那应该不是问题。

对于原始 OP 来说可能为时已晚,但可能会帮助其他人。您可以简单地 return SETOF tabletype 代替。我修改了原始代码作为示例。

CREATE FUNCTION test() RETURNS SETOF my_table AS
$$
    DECLARE
        q4 my_table;
    BEGIN
        FOR q4 IN SELECT * FROM my_table LOOP
            RETURN NEXT q4;
        END LOOP
    END;
$$
LANGUAGE plpgsql;