【问题标题】:How does Oracle perform OR condition validation?Oracle 如何执行 OR 条件验证?
【发布时间】:2015-12-14 04:44:36
【问题描述】:

在 Java 中,逻辑 OR 条件的行为是,如果第一个条件是 true,那么它不会评估第二个条件。

例如:

int a = 10;
if (a == 10 || a == 0) {
    // Logic
}

Java 不会评估第二个测试 (a == 0),因为第一个条件 (a == 10) 是 true

如果我们有这样的 Oracle SQL 语句:

select * from student where city = :city and 
    (:age is null or age > :age)

如何评估(age > :age or :age is null)?如果参数:ageNULL,那么它是否也计算第二个条件?

【问题讨论】:

    标签: sql oracle logical-operators


    【解决方案1】:

    数据库成本优化器在构建查询执行结构时会考虑许多因素。最重要的可能是相关列上是否存在索引。它将根据测试的选择性决定顺序,并可以在不同的时间以不同的顺序执行它们。由于 SQL 是一种声明性而非过程性语言,因此您通常无法控制评估这些条件的方式。

    您可以提供一些“提示”来建议特定的执行顺序,但您可能会对性能产生不利影响。

    【讨论】:

    • 可能通过使用子查询来影响评估顺序。
    【解决方案2】:

    PL/SQL

    在 PL/SQL 中,Oracle OR 是 短路 评估的另一个示例。 Oracle PL/SQL Language Fundamentals 说(部分)

    短路评估

    在评估逻辑表达式时,PL/SQL 使用短路评估。也就是说,PL/SQL 会在确定结果后立即停止计算表达式。因此,您可以编写可能导致错误的表达式。

    SQL

    但是,在常规 SQL 中,OR 可能按任一顺序计算。正如@JonHeller 在他的评论中指出的那样这个问题中的表达式是安全的,如果处理可能被 0 分割,则需要更加谨慎

    【讨论】:

    • 感谢您的回复。所以你能建议在sql下面写什么最好的方法吗? (:age 为 null 或 age > :age) 或 ( age > :age 或 :age 为 null )。大多数时候 :age 为空。
    • 我建议你在测试一个值之前测试null,因为它会首先评估为true
    • 这对于 PL/SQL 是正确的,但对于 Oracle SQL 是不正确的。您不能编写可能导致错误的表达式,因为您不能依赖从左到右的短路评估。例如,请参阅this question。虽然这个问题中的表达式是安全的,但如果处理潜在的除以 0,则需要更加谨慎。
    • @JonHeller 谢谢。已编辑。
    【解决方案3】:

    让 Oracle 为您做出决定。在大多数情况下,它会做出更好的决定。在这种情况下,甚至还有一个将 null 测试与值测试相结合的结构。

    替换

    :age is null or age > :age
    

    age > nvl(:age, age - 1)
    

    【讨论】:

    • 等价的表达式是age > nvl(:age, age-1),不是吗?无论如何,这是一个很好的建议:-)
    • -1 用更复杂的表达式替换表达式是一个非常糟糕的建议。如果您有 OR 表达式,Oracle 会为您完成这项工作,还是 Oracle 会询问您如何评估它?如果你现在引入一个函数(NVL),这个表达式对于oracle来说真的很难优化。它现在必须评估每一行以找出谓词的值。与此相反,如果 :age 为空,则它不必评估任何行,如果年龄不为空,它将无法使用索引。
    猜你喜欢
    • 1970-01-01
    • 2016-10-11
    • 2011-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多