从plpgsql函数返回行集。

时间:2015-09-28 13:52:21

标签: sql postgresql plpgsql

我想从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;

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

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

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

3 个答案:

答案 0 :(得分:3)

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则返回行集。
  • 您必须选择一行作为一个值,因为该变量属于复合类型。

使用循环的示例:

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

的文档

答案 1 :(得分:3)

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

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返回复合值 - 它不是表。但是你可以编写一些返回复合值集的函数 - 它就是表。

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;

仔细使用这些功能。它们是优化器的黑盒子,因此优化器不能同时优化函数和外部查询中的查询,它必须单独优化这些查询,这对于某些复杂查询不应该有效。当外部查询很简单时,它应该不是问题。

答案 2 :(得分:1)

对于最初的OP来说可能为时已晚,但可能会帮助其他人。您只需返回SETOF表格类型即可。我修改了原始代码作为示例。

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;