首页 > 数据库 > mysql教程 > 在 PostgreSQL 中使用 `(func()).*` 时如何避免多次函数求值?

在 PostgreSQL 中使用 `(func()).*` 时如何避免多次函数求值?

DDD
发布: 2025-01-10 11:19:42
原创
407 人浏览过

How Can I Avoid Multiple Function Evaluations When Using `(func()).*` in PostgreSQL?

*PostgreSQL 中避免使用 `(func()).` 导致的函数重复调用**

在 PostgreSQL 中,使用 (func()).* 语法访问返回表或复合类型的函数结果,可能会导致对每个列重复调用该函数。这会影响性能,尤其是在函数计算成本较高的情况下。

解决方案

为了避免这个问题,您可以将函数调用包装在一个子查询中,如下所示:

<code class="language-sql">SELECT (mf).* FROM (
    SELECT my_func(x) AS mf FROM some_table
) sub;</code>
登录后复制
登录后复制

这样可以确保函数只被调用一次,而不管结果中有多少列。或者,在 PostgreSQL 9.3 及更高版本中,您可以使用 LATERAL JOIN 语法:

<code class="language-sql">SELECT mf.*
FROM some_table
LEFT JOIN LATERAL my_func(some_table.x) AS mf ON true;</code>
登录后复制

问题原因

重复调用发生是因为解析器将 (func()).* 视为列名列表的占位符。它将表达式宏展开为一系列单独的列,从而导致多次调用函数。

演示

为了演示这个问题和解决方案,创建一个函数:

<code class="language-sql">CREATE OR REPLACE FUNCTION my_func(integer)
RETURNS TABLE(a integer, b integer, c integer) AS $$
BEGIN
    RAISE NOTICE 'my_func(%)',;
    RETURN QUERY SELECT , , ;
END;
$$ LANGUAGE plpgsql;</code>
登录后复制

以及一个包含虚拟数据的表:

<code class="language-sql">CREATE TABLE some_table AS SELECT x FROM generate_series(1,10) x;</code>
登录后复制

比较以下查询的结果:

  • 原始语法:
<code class="language-sql">SELECT (my_func(x)).* FROM some_table;</code>
登录后复制
  • 解决方案语法:
<code class="language-sql">SELECT (mf).* FROM (
    SELECT my_func(x) AS mf FROM some_table
) sub;</code>
登录后复制
登录后复制

您会注意到,原始语法会引发多次通知,而解决方案语法只引发一次通知,这证明了避免了多次函数调用的效果。

以上是在 PostgreSQL 中使用 `(func()).*` 时如何避免多次函数求值?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板