(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中文网其他相关文章!