返回多列的plpgsql函数被多次调用

Posted

技术标签:

【中文标题】返回多列的plpgsql函数被多次调用【英文标题】:plpgsql function that returns multiple columns gets called multiple times 【发布时间】:2013-02-21 09:53:39 【问题描述】:

我正在运行 PostgreSQL 9.2.1 并且有一个返回 3 列的 plpgsql 函数。它是这样调用的(简化):

SELECT (my_function(b.input)).*, a.other, b.columns
FROM table_a a
JOIN table_b b ON a.id = b.id
WHERE ...

该函数打印出一条警告消息,我惊讶地发现它打印了 3 次。看起来该函数被调用了 3 次 - 大概每列一次。这对性能没有好处!我怎样才能确保它只被调用一次?它已被标记为 STABLE。

如果我称之为

SELECT * FROM my_function(input)

然后警告只打印一次,但我不知道如何将它集成到更大的查询中,并返回连接和其他列。也就是说,当我需要 FROM 列表中的其他表并且函数从这些表中获取输入时,我不知道如何将函数放入 FROM 列表中。

编辑

查询(更接近原始):

SELECT (my_aggregate_function(sub1.border, sub1.lower_limit, sub1.upper_limit, operation)).*
FROM
(
    SELECT (my_function(ca.timeslice_id)).*, agc.operation
    FROM geometry_component agc
    JOIN volume av ON agc.volume_id = av.id
    JOIN volume_dependency avd ON av.contributor_id = avd.id
    JOIN my_rowset_function('2013-02-22') ca ON avd.id = ca.feature_id
    WHERE agc.timeslice_id = 12345
    ORDER BY agc.sequence
) sub1

my_aggregate_functionmy_function 各返回 3 列(border、lower_limit、upper_limit),但 my_aggregate_function 是聚合,my_function 是常规函数。

【问题讨论】:

昨天密切相关的问题:***.com/questions/14965708/…。请提供您的查询,应该可以实现子查询。 感谢您的链接,但我无法从中弄清楚。我已经添加了查询。 【参考方案1】:

这应该可以完成工作:

SELECT (y).*
FROM  (
   SELECT my_aggregate_function(border, lower_limit, upper_limit, operation) AS y
   FROM (
      SELECT (x).*, operation
      FROM  (
         SELECT my_function(ca.timeslice_id) AS x, agc.operation
         FROM   geometry_component agc
         JOIN   volume             av  ON av.id = agc.volume_id
         JOIN   volume_dependency  avd ON avd.id = av.contributor_id
         JOIN   my_rowset_function('2013-02-22') ca ON ca.feature_id = avd.id
         WHERE  agc.timeslice_id = 12345
         ORDER  BY agc.sequence
         ) sub1
      )sub2
   )sub3

【讨论】:

谢谢你,Erwin,你是 PostgreSQL 问题的 Jon Skeet! 我想知道为什么 PostgreSQL 在内部不这样做。有趣的是,聚合函数只被调用一次(没有上述解决方法),即使它也返回多个列。至少我的累加器函数每行只调用一次。 @EM:哦,Jon Skeet 真是太荣幸了! ;) 我认为它是当前版本中查询计划器的一个弱点。 Postgres 开发人员专注于将LATERAL 纳入 9.3 版本,这应该为此类问题提供更有效的方法。【参考方案2】:

不幸的是,这是实现的正常怪癖。当 9.3 支持 LATERAL 查询时,可以避免这个问题。

目前我不知道有什么好的解决方法。

【讨论】:

以上是关于返回多列的plpgsql函数被多次调用的主要内容,如果未能解决你的问题,请参考以下文章

返回查询时如何退出plpgsql函数

Plpgsql - 多次迭代记录集

检查 plpgsql 中的当前日志记录级别

plpgsql:使用 2 个 OUT 参数调用函数

为啥我的 plpgsql 函数不返回任何行

Postgresql - 从 plpgsql 函数返回记录 []