【问题标题】:Using the OR operator - SQL Server使用 OR 运算符 - SQL Server
【发布时间】:2019-07-04 02:24:03
【问题描述】:

我正在阅读有关 OR 运算符的文档,上面写着:

大多数更好的 DBMS 甚至不会评估第二个条件 如果第一个条件已经满足,则为 OR WHERE 子句。 (如果 满足第一个条件,无论 第二个条件)。

SELECT prod_code, prod_price
FROM Articles
WHERE Code = '1' OR Code = '2'

这是否意味着如果 Code = '1' 查询将返回所有带有 '1' 的值,忽略第二个条件 WHERE Code = '2'。

我在 SQL Server 上对此进行了测试,它返回所有值为 1 的值和所有值为 2 的值,所以实际上是 2 行......

所以我在这里有点困惑?

谢谢 干杯

【问题讨论】:

  • 这意味着如果一行满足Code = 1 的条件,那么它不会评估该行的子句Code = 2。这并不意味着它会停止检查其余行。 RDBMS 仍将返回满足其中任一要求的每一行。
  • @Larnu aaa 该行是关键!书中没有这部分句子! :) 谢了哥们!因此,如果发现 Code=1,RDBMS 将转到下一行,不会检查同一行两次!谢谢
  • 这可能意味着 不同 列的条件,例如colA = 'foo' or colB between 1 and 5

标签: sql sql-server sql-server-2008 logical-operators


【解决方案1】:

该声明只是关于优化,称为“短路”。意思是当1 匹配条件时,不会与2 进行比较。因为与 2 的比较结果无关紧要。

你说的好像有点糊涂

如果 Code = '1' 查询将返回所有带有 '1' 的值,忽略第二个条件 WHERE Code = '2'。

Code 是每一行中的一列,而不是对所有行都保持不变的总体值。 (如果是这样,在 SQL Server 中将是 @Code,而不是 @Code。)

不过,对于您的示例,您应该使用IN:

WHERE Code IN ('1', '2')

而且,如果Code 是数字,那么比较值不应包含单引号。

【讨论】:

  • 我今天开始学习mssql,所以我有点困惑,但现在更清楚了,书的作者意味着一行,如果一行代码的值为1,那我为什么要这样做需要检查 Code 的值是否等于 2,因为它肯定不是因为我已经找到了 1 的值,所以让我们再检查一行!对吗?
  • @rokie12234 。 . .确切地。这是所有编程语言(至少支持条件逻辑的语言)的标准优化。它不是 SQL 特有的。
  • @rokie12234 - 这并不是因为它知道Code 绝对不等于 2,而是因为它是什么并不重要
【解决方案2】:

摘自我原来的评论: 这意味着如果一行满足Code = 1 的条件,那么它将不会评估该行的子句Code = 2。这并不意味着它会停止检查其余行。 RDBMS 仍将返回满足其中任一要求的每一行。

所以如果我们有这样的表:

CREATE TABLE YourTable (ID int IDENTITY,
                        Code int,
                        SomeValue varchar(10));
INSERT INTO YourTable (Code,SomeValue)
VALUES (1,'asdkjsa'),
       (1,'asdojsa'),
       (2,'saohdsald'),
       (3,'sdfkjhsadk'),
       (3,'asdkjsagd');

如果您要运行查询 SELECT * FROM YourTable WHERE Code = 1 OR Code = 2;,那么对于第二个 1st 2 行,将不会评估 OR Code = 2,因为 Code = 1 已经评估为 true。

但是,您可以使用更简洁的运算符IN:WHERE Code IN (1,2),而不是使用WHERE Code = 1 OR Code = 2。

【讨论】:

    【解决方案3】:

    这是否意味着如果 Code = '1' 查询将返回所有 带有 '1' 的值忽略第二个条件 WHERE Code = '2'。

    每一行在 Code 列有 1 个值。
    扫描表时,检查WHERE 子句中的条件。
    如果您使用的 rdbms 执行 短路评估,那么在 OR:
    的情况下,如果值是 '1',那么它也不会与 '2' 比较,因为它不需要并移动到下一行。
    如果该值不是'1',那么它将与'2' 进行另一次比较。
    所以回答你的问题:
    带有Code = '2' 的行不会被忽略。
    条件检查在不需要时被忽略。

    【讨论】:

      【解决方案4】:

      您的示例搜索条件是

      Code = '1' OR Code = '2'
      

      这是一个布尔表达式,它本身由两个子布尔表达式和OR 组合而成。

      • Code = '1'
      • Code = '2'

      在 SQL 中,布尔表达式可以有三个可能的真值true、false、unknown。

      当将表达式与AND 或OR 结合使用真值表时,可用于扩展所有可能的结果。 OR 的真值表如下。

      ╔═════════╦══════╦═════════╦═════════╗
      ║         ║ TRUE ║  FALSE  ║ UNKNOWN ║
      ╠═════════╬══════╬═════════╬═════════╣
      ║ TRUE    ║ TRUE ║ TRUE    ║ TRUE    ║
      ║ FALSE   ║ TRUE ║ FALSE   ║ UNKNOWN ║
      ║ UNKNOWN ║ TRUE ║ UNKNOWN ║ UNKNOWN ║
      ╚═════════╩══════╩═════════╩═════════╝
      

      通过查看上表可以看出,如果您知道其中一个子表达式为真,则另一个表达式的值无关紧要。整个组合表达式的值仍然是true,所以甚至不需要计算它。

      SQL Server 可以进行短路评估,但 it doesn't guarantee that it will。

      此外,它可能会提出一个执行计划,其中两个谓词甚至不相关,无法一起评估。它可能会为问题中的查询提出一个计划,其中包含一个索引搜索运算符和两个搜索。一个在Code = '1',一个在Code = '2'。

      现在可以从执行计划中删除单独的谓词评估,因为可以保证这些索引查找的组合结果将匹配 WHERE 子句,因此除了会发生的情况之外,无需进行任何额外的谓词评估作为这些寻求的一部分。

      【讨论】:

        猜你喜欢
        • 2014-05-05
        • 2015-02-17
        • 2017-08-01
        • 1970-01-01
        • 2019-10-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-02
        相关资源
        最近更新 更多