问题描述
1. SELECT CASE WHEN (1=1) THEN NULL ELSE cast(1/0 as text) END;
2. SELECT CASE WHEN (EXISTS (SELECT 10)) THEN NULL ELSE cast(1/0 as text) END;
您可能已经注意到两个查询中第一个条件的结果为真,但第一个查询的结果是 null
,第二个查询的结果是 ERROR: division by zero
这里发生了什么?
在评估发生的顺序上是否有任何优化?如果是,是否有任何原因将其关闭?
当条件结果为真时,是否有任何原因在条件块中有一个复杂的查询,而不会在 else 块中触发运行时错误?
Postgresql 版本:13.1
解决方法
错误发生在计划查询时,而不是运行时。
在第一种情况下,在计划时已知 1=1 为真,导致整个 CASE 折叠为 NULL::text。因此,1=1
和 CASE WHEN true
的常量折叠使您免于 1/0
的常量折叠异常。您可以通过执行 EXPLAIN VERBOSE 来看到这一点。
当条件结果为真时,是否有任何原因在条件块中有一个复杂的查询,而不会在 else 块中触发运行时错误?
是的,除非它不是真正在运行时出现问题。
就像一个虚拟的 SELECT 打败了防止问题的常量折叠,另一个虚拟的 select 可以打败导致问题的常量折叠。
SELECT CASE WHEN (EXISTS (SELECT 10)) THEN NULL::text ELSE cast (1/(select 0) as text) END;