我有一个Oracle查询,其结构如下:
SELECT *
FROM table
WHERE X='true' OR
Y IN (complicated subquery)
如果Oracle认为X确实等于'true',它仍然会尝试评估WHERE子句的Y IN(子查询)部分吗?此外,在诸如此类的语句中,子查询是否会对表中的每个条目执行多次?我会用以下的东西变得更好:
WITH subQ as (complicated subquery)
SELECT *
FROM table
WHERE X='true' OR
Y IN (SELECT id FROM subQ)
答案 0 :(得分:31)
这取决于。
。
通常,Oracle不保证SQL语句将使用短路评估(尽管PL / SQL可以保证执行短路评估)。 Oracle优化器可以以任何预期最有效的顺序自由地评估谓词。这可能意味着首先评估第一个谓词,只评估匹配行的第二个谓词,但完全可能发生相反的情况,或者Oracle将查询转换为UNION
类并完全评估两个谓词在结合结果之前。
话虽如此,如果优化器可以在编译时确定谓词将始终评估为TRUE
或FALSE
,优化器应该将其视为常量。因此,例如,如果表上存在阻止X
具有值'true'的约束,则优化器根本不应评估第二个谓词(尽管优化器的不同版本将具有在编译时检测某些东西是常量的不同能力。)
至于你问题的第二部分,没有看到查询计划,很难说。如果有更有效的评估方法,Oracle优化器往往非常擅长将查询从一种形式转换为另一种形式。但是,一般情况下,如果subQ
与table
相比将返回相对较多的行,则将查询结构化为EXISTS
而不是{{}}可能更有效{1}}。
答案 1 :(得分:12)
警告:Oracle不是我的主要专业领域。
基于成本的优化器应该知道X = 'true'
的成本低于子查询,因此它可能首先评估更简单的替代方案。但是SQL中的AND和OR条件不短路,如&&
和||
在C及其派生词中。
子查询可以是两种形式之一:相关和非相关。
示例相关子查询:
SELECT *
FROM Table1
WHERE X = 'true'
OR Y IN (SELECT Z FROM Table2 WHERE Table2.A = Table1.B)
非相关子查询示例:
SELECT *
FROM Table1
WHERE X = 'true'
OR Y IN (SELECT Z FROM Table2 WHERE Table2.A > 13)
答案 2 :(得分:1)
无论优化程序对dd<-data.frame(a = c("11234", "000aa456", "a234", "00aa450009"))
和AND
可能做什么或不做什么,如果由于任何原因您必须强制执行特定的评估顺序,您可以使用其他工具重写查询 - 保证电路评估。
例如:
OR
如果X是真的&#39;然后case表达式求值为1,第二个&#34;当&#34;被跳过,条件评估为TRUE。如果X不是真的&#39;然后评估IN条件。
答案 3 :(得分:1)
我来这里的目的是寻找有关如何通过短路评估避免崩溃的答案。我最终得到的是:
...
where case when [its not going to crash]
then [short circuit expression]
else [safe, never used value]
end = comparison_value
...
因此,例如,如果您担心to_number表达式崩溃,则可以在when子句中添加“ REGEXP_LIKE(my_possible_number,'^ [[:digit:]] + $')”之类的内容(对于正整数) -调整为非正数或非整数。