从 plpgsql 函数返回一组行。

Art*_*ski 5 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;
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

    Error: ERROR:  syntax error at or near "SELECT"
    LINE 5:  q4 := SELECT * FROM my_table;
Run Code Online (Sandbox Code Playgroud)

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

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

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

kli*_*lin 8

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;
Run Code Online (Sandbox Code Playgroud)
  • 您不能在函数中使用变量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();
Run Code Online (Sandbox Code Playgroud)

阅读有关从函数返回的文档

  • 一般来说,数据更新应该使用 UPDATE 语句在纯 SQL 中完成。函数内的迭代效率较低且更麻烦。基本上,您不能*将整个查询分配给变量*。您可以使用游标、临时表、视图等。我认为您应该提出一个具有更具体问题的新问题。 (2认同)

Pav*_*ule 5

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

\n\n
CREATE TABLE xx(a int, b int);\n\nCREATE OR REPLACE FUNCTION foo()\nRETURNS xx AS $$\nDECLARE v xx;\nBEGIN\n  v := (10,20);\n  RETURN v;\nEND;\n$$ LANGUAGE plpgsql;\n
Run Code Online (Sandbox Code Playgroud)\n\n

函数foo返回复合值 - 它不是表。但是您可以编写一些返回复合值集的函数 - 它是表。

\n\n
CREATE OR REPLACE FUNCTION foo(a int)\nRETURNS SETOF xx AS $$\nDECLARE v xx;\nBEGIN\n  FOR i IN 1..a LOOP\n    v.a := i; v.b := i+1;\n    RETURN NEXT v;\n  END LOOP;\n  RETURN;\nEND;\n$$ LANGUAGE plpgsql;\n\npostgres=# SELECT * FROM foo(3);\n\xe2\x94\x8c\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xac\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x90\n\xe2\x94\x82 a \xe2\x94\x82 b \xe2\x94\x82\n\xe2\x95\x9e\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xaa\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa1\n\xe2\x94\x82 1 \xe2\x94\x82 2 \xe2\x94\x82\n\xe2\x94\x82 2 \xe2\x94\x82 3 \xe2\x94\x82\n\xe2\x94\x82 3 \xe2\x94\x82 4 \xe2\x94\x82\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xb4\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x98\n(3 rows)\n
Run Code Online (Sandbox Code Playgroud)\n\n

当结果基于查询时,您可以使用RETURN QUERY. FOR IN SELECT它比and更快、更短、更易读RETURN NEXT

\n\n
CREATE OR REPLACE FUNCTION foo2(a int)\nRETURNS SETOF xx AS $$\nBEGIN\n  RETURN QUERY SELECT * FROM xx\n                  WHERE xx.a = foo2.a;\n  RETURN;\nEND;\n$$ LANGUAGE plpgsql;\n
Run Code Online (Sandbox Code Playgroud)\n\n

小心使用这些功能。它们对于优化器来说是一个黑匣子,因此优化器不能同时优化函数内查询和外部查询,它必须单独优化这些查询,这对于一些复杂的查询应该无效。当外部查询很简单时,那么它应该不是问题。

\n