调用返回记录的 Postgres 函数,传入查询结果

Jef*_*f G 2 sql postgresql function plpgsql postgresql-9.3

问题是我需要运行一个查询(仅在运行时知道)来确定我的函数的输入参数,它需要返回一个结果。例如,我想写:

CREATE FUNCTION foo(inputKey INT) RETURNS TABLE (c0 INT, c1 TEXT) AS $$
    BEGIN
        -- Do something with inputKey to compute and return result
    END;
$$ LANGUAGE PLPGSQL;
Run Code Online (Sandbox Code Playgroud)

这些是我迄今为止尝试过的查询:

-- Doesn't even run (exception)
SELECT * FROM foo(SELECT foreignKey FROM someTable WHERE primaryKey = 5);

-- Runs, but returns a single column with all columns listed in it's value
SELECT foo(foreignKey) FROM someTable WHERE primaryKey = 5;

-- Same problem as previous
SELECT * FROM (SELECT foo(foreignKey) FROM someTable WHERE primaryKey = 5) AS a
Run Code Online (Sandbox Code Playgroud)

我也尝试将结果类型更改为

  • myType (CREATE TYPE myType AS (c0 INT, c1 TEXT))
  • SETOF myType
  • RECORD
  • SETOF RECORD

以上所有表现出相同的行为。

通过调用返回记录、表或记录集的 plpgsql 函数获取多列结果的语法是什么?这个问题听起来很简单,但经过无数次互联网搜索后,我一直无法弄清楚这个问题的语法。我在网上找到的所有问题都使用了语法SELECT * FROM function(),绝对没有有人从另一个查询传递输入参数的例子。

Erw*_*ter 5

通过调用返回记录、表或记录集的 plpgsql 函数获取多列结果的语法是什么?

这实际上是两三个不同的问题。

  • tablesetof record密切相关(“表”意味着定义明确的行类型,而记录可以定义明确或匿名,需要不同的处理)。
    @Kirk函数提供了解决方案

  • 返回单个记录的函数是一种不同的情况。这些允许更多的方式来调用它们。喜欢:

    SELECT foo(foreignkey).*  -- decomposing is simple for well-known types
    FROM   sometable
    WHERE  primarykey = 5;
    
    Run Code Online (Sandbox Code Playgroud)

Postgres 查询规划器在那里有一个弱点,并以这种方式多次评估该函数。在 Postgres 9.3 中,LATERAL对于返回多列的昂贵函数,使用连接代替:

    SELECT f.*
    FROM   sometable s
    LEFT   JOIN LATERAL foo(s.foreignkey) f ON true
    WHERE  s.primarykey = 5;
Run Code Online (Sandbox Code Playgroud)

细节: