首页 >数据库 >mysql教程 >在 SQL 查询中使用 `(func()).*` 时如何防止多个函数调用?

在 SQL 查询中使用 `(func()).*` 时如何防止多个函数调用?

Linda Hamilton
Linda Hamilton原创
2025-01-10 11:51:42531浏览

How to Prevent Multiple Function Calls When Using `(func()).*` in SQL Queries?

在 SQL 查询中使用 (func()).* 避免重复函数调用

当使用返回表或复合类型的函数时,(func(arg)).* 语法可能会导致每个输出列的冗余函数调用。 在表或子查询中调用函数时会出现此问题,其中 (func()).* 通常是唯一实用的方法。

问题

意外的是,(func()).* 触发了多个函数执行——数量等于输出列数。 例如,返回四列的函数可能会被调用八次,而不是预期的两次。

解决方案

要纠正此问题,请将函数调用封装在子查询中:

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

这通常可以避免额外的函数调用,并且不会引入额外的运行时扫描。 为了绝对确定,请考虑 OFFSET 0 技巧或利用 PostgreSQL 在 CTE 优化方面的限制:

<code class="language-sql">SELECT (mf).* FROM (
    SELECT my_func(x) AS mf FROM some_table OFFSET 0
) sub;

WITH tmp(mf) AS (
    SELECT my_func(x) FROM some_table
)
SELECT (mf).* FROM tmp;</code>

PostgreSQL 9.3 及更高版本提供了更优雅的解决方案,使用 LATERAL:

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

根本原因

解析器将 (func()).* 扩展为列列表是根本原因。 解析后的树显示 (func(x)).* 转换为:

<code>(my_func(x)).i, (my_func(x)).j, (my_func(x)).k, (my_func(x)).l</code>

这种低效的节点克隆,而不是单个函数调用节点复制,导致了重复调用。

以上是在 SQL 查询中使用 `(func()).*` 时如何防止多个函数调用?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn