【问题标题】:Accessing the Return Table in a Postgres Function在 Postgres 函数中访问返回表
【发布时间】:2016-03-20 00:30:04
【问题描述】:

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

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;

【问题讨论】:

  • 这个函数到底是做什么的?
  • @a_horse_with_no_name 上面显示的函数正在将 3 个值插入到返回表中,然后更新插入的值之一,即值为 3 的值。基本上我需要知道如何更新已经插入到返回表中的数据。如果可以更好地澄清,我可以在 Postgres 中发布一个示例。
  • 当用正确的表名替换无效的@table 标识符时,插入和更新的编写方式可以相同(使用values 子句,插入实际上可以写得更短)。但是单曲return最后做了什么?它返回什么?
  • @a_horse_with_no_name 它不返回任何内容,在 MSSQL 中编写此类函数时需要它。我不确定您所说的“在替换无效的@table 标识符时可以以相同的方式编写”是什么意思。我会在 Postgres 中用什么替换它?我知道 INSERT 会变成 RETURN QUERY。
  • @a_horse_with_no_name 我编辑了我的问题以包含一个 Postgres 示例,如果这有帮助的话。

标签: sql-server postgresql function plpgsql


【解决方案1】:

使用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;

【讨论】:

  • 我知道我可以使用临时表,但我尽量避免这种情况,因为 MSSQL 不需要它。听起来好像我不能。谢谢你的澄清。
  • 第一个查询应该是 VALUES (1),(2) 以返回两行一列而不是一行两列 - 这在这种情况下不起作用。所有这些都可以是IMMUTABLE,而不仅仅是STABLE。在第二个示例中,您不需要子查询。它可以是一个简单的 SQL 函数...
  • 是否可以访问已经插入的值?在第一个示例中,您对 1 和 2 执行 RETURN QUERY。有没有办法像在 MSSQL 中一样通过从 @table 中选择来使 1 和 2 退出?
  • @Billy:不,不在同一个函数中。结果集一旦返回就无法访问,就像 pozs 解释的一样(这里没有“插入”)。您可以从 another 函数调用该函数来更改结果行,但这通常不是必需的。或者,您可以使用实际的临时表进行更复杂的操作,在函数内部或外部创建。
  • @ErwinBrandstetter 感谢您的澄清。是的,它应该是VALUES (1), (2)。我故意将函数的签名留在问题中。我假设,这只是一个更复杂功能的简化版本。如果不是这样,一个简单的VALUES(1),(2),(-1) 甚至无需定义函数即可完成这项工作。
【解决方案2】:
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) 的简单情况。你可以使用任何一个。

相关答案(许多其他):

对于更复杂的操作,您可以使用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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-13
    • 1970-01-01
    • 2013-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多