在 PostgreSQL 中重用存储过程的结果

Posted

技术标签:

【中文标题】在 PostgreSQL 中重用存储过程的结果【英文标题】:Reuse of stored procedure results in PostgreSQL 【发布时间】:2016-10-13 20:48:00 【问题描述】:

我正在研究 PostgreSQL 数据库的只读副本,不可能创建任何临时表(只读事务)。

考虑我有存储过程foo(...) 它返回我TABLE(...) 结果(或SETOF Foo_Type 相同)。

这个Foo_Type 有一些type 字段,用于定义行中的数据类型。

在另一个具有固定返回类型的过程foo_wrapper(...)(它也是TABLE(...) 或者说SETOF Foo_Wrapper_Type)中,我需要执行以下操作:

取决于Foo_Type.type 的值,我需要使用left join 将来自foo(...) 的结果与不同的表合并。目前是这样处理的:

...
return query
select
   ft.*,
   a1.x1
   from foo(param1, param2, ...) ft
   left join a_table a on ...
   where ft.type = 'value_1'

union
select
   ft.*,
   b1.x1
   from foo(param1, param2, ...) ft
   left join b_table b on ...
   where ft.type = 'value_2'

...

union-s 有几十个。

不要告诉我我的 Schema 设计得多么邪恶和糟糕。我知道,它是遗留模式。

我要问的是如何避免在此语句中多次调用foo(...) 过程?

这个foo_wrapper(...) 程序运行非常缓慢。我怀疑这是因为多次调用具有相同参数的foo(...) 过程,我不确定数据库是否将其结果缓存在一个会话中。

所以我的问题由两部分组成:

    在我的大联合选择之前,有什么方法可以“提取”并保存 foo(...) 的结果? DECLARE results SETOF Foo_Type 不起作用。

    这可能不是优化的重点,有人肯定会声称foo(...) 的第一次调用的结果被缓存以供此过程中的进一步调用?

【问题讨论】:

【参考方案1】:

使用公用表表达式:

return query
with foo_data as (
  select * 
  from foo(param1, param2, ...)
)
select ft.*,
       a1.x1
from foo_data ft
  left join a_table a on ...
where ft.type = 'value_1'
union 
select ft.*,
       b1.x1
from foo_data ft
   left join b_table b on ...
where ft.type = 'value_2'
...

您可能想使用union all 而不是union

【讨论】:

哇,看起来像是一个决定。我明天会检查它,我的投票和检查不会延迟!谢谢!

以上是关于在 PostgreSQL 中重用存储过程的结果的主要内容,如果未能解决你的问题,请参考以下文章

在存储过程中重用大型 SQL 查询

Informix SQL / 在另一个查询中重用存储过程的结果

PostgreSQL存储过程

如何使用 JDBC 调用 PostgreSQL 存储过程

为啥我在从 Java 批量执行 PostgreSQL 存储过程时收到错误消息,提示“未预期结果”?

PostgreSQL存储过程-基于SQL的存储过程