在 Postgres 函数中访问 Return Table

Accessing the Return Table in a Postgres Function

在 MSSQL 中,当在多语句 table 值函数中时,您可以使用 table 进行交互,如下所示。

CREATE FUNCTION dbo.test_func() RETURNS @table TABLE(id INT) AS
BEGIN
    INSERT INTO @table(id)
    SELECT 1 UNION SELECT 2 UNION SELECT 3

    UPDATE @table SET id = -1 WHERE id = 3
    RETURN
END
GO

有没有办法在 Postgres 9.5 中完成此操作?我不确定要更新什么,如下所示。

CREATE FUNCTION test_func() RETURNS TABLE(id int) AS $$
BEGIN
    return QUERY SELECT 1 UNION SELECT 2 UNION SELECT 3;
    UPDATE ???? SET id = -1 WHERE id = 3;
END;
$$ LANGUAGE plpgsql STABLE;

函数的结果集在使用 RETURN NEXT or RETURN QUERY 发送后无法更改。

但是在 PostgreSQL 中,您不必在单个语句中发送整个结果集(这就是为什么您的要求在 PostgreSQL 中毫无意义)。您可以使用 RETURN NEXT 将行逐行发送到结果集,您可以使用 RETURN QUERY/RETURN QUERY EXECUTE 发送结果集的块,或者甚至可以混合使用。 (您也可以使用不带参数的单个 RETURN 退出该函数)。

所以,您可能想要做的是:

CREATE FUNCTION test_func() RETURNS TABLE(id int) AS $$
BEGIN
    RETURN QUERY VALUES (1), (2);
    -- do some calculation
    RETURN NEXT -1;
END;
$$ LANGUAGE plpgsql STABLE;

如果你真的想模仿what MSSQL does,你可以使用临时表,或者(最好)在函数内部进行子选择:

CREATE FUNCTION test_func() RETURNS TABLE(id int) AS $$
BEGIN
    RETURN QUERY SELECT (SELECT CASE WHEN v = 3 THEN -1 ELSE v END res)
                 FROM   (VALUES (1), (2), (3)) v;
END;
$$ LANGUAGE plpgsql STABLE;
CREATE FUNCTION test_func()
  RETURNS TABLE(id int) AS
$func$
BEGIN
   RETURN QUERY
   SELECT CASE WHEN v = 3 THEN -1 ELSE v END
   FROM   (VALUES (1), (2), (3)) v;
END
$func$ LANGUAGE plpgsql IMMUTABLE;

根本不需要 PL/pgSQL。一个简单的 SQL 函数就可以做到:

CREATE FUNCTION test_func()
  RETURNS SETOF int AS
$func$
   SELECT CASE WHEN v = 3 THEN -1 ELSE v END
   FROM   (VALUES (1), (2), (3)) v;
$func$ LANGUAGE sql IMMUTABLE;

还演示了简单形式 SETOF int 而不是简单情况下的 TABLE(id int)。您可以使用任何一种。

相关答案(在许多其他人中):

  • PostgreSQL function returning multiple result sets
  • How to return result of a SELECT inside a function in PostgreSQL?

对于更复杂的操作,您可以使用 CTE

CREATE FUNCTION test_func()
  RETURNS SETOF int AS
$func$
   WITH v(id) AS (VALUES (1), (2), (3))
   SELECT CASE WHEN id = 3 THEN -1 ELSE id END
   FROM   v
$func$ LANGUAGE sql IMMUTABLE;

对于更复杂的工作,您可以使用实际的 temporary table:

  • PostgreSQL table variable

  • Select from a table variable