【问题标题】:Not Equal logic trouble in SQL ServerSQL Server 中的不等于逻辑问题
【发布时间】:2015-02-25 15:52:58
【问题描述】:

我不敢相信我在这方面遇到了这么多麻烦。

使用这个语句:

USE XXXX

SELECT 
    ID, DESCRIPTION, STATUS
FROM 
    PART
WHERE 
    PART.ID LIKE 'PCH%'
    AND PART.DESCRIPTION NOT LIKE '%OBSOLETE%'
    AND PART.STATUS = 'O'

我得到一个包含 34 个条目的表,每个条目都包含 PART.STATUS 中的 O。

我真正想说的是,只显示不具有 O 状态的值。我知道还有其他方法可以解决这个问题。不是 O 的值应该为空,但我很生气,我无法弄清楚“不等于”语句是如何工作的。当我将最后一行切换为:

AND PART.STATUS <> 'O'

AND PART.STATUS != 'O'

我得到一个空表返回。

如果我使用这条线

AND PART.STATUS IS NULL

我得到了我要找的桌子。

我对“不相等语句”的使用有什么误解?

【问题讨论】:

  • 通过使用is null,你得到了你想要的吗?
  • 不能NULL使用正常的等式(=)或不等式(&lt;&gt;)运算符 - 对NULL使用这些运算符不会返回一个合适的值 - 它返回NULL。为了检查NULL,您必须使用IS NULLIS NOT NULL - 没有其他方法

标签: sql logical-operators


【解决方案1】:

问题是三值谓词逻辑。当谓词的至少一侧为NULL 时,谓词的结果为UNKNOWN(无论您使用=&lt;&gt;&gt;&lt;,...),但WHERE 子句仅返回谓词计算结果为 TRUE 的行。所以我们的工作是在PART.STATUS IS NULL 时创建谓词以评估TRUE。这是通过在NULL 上添加额外检查来完成的,例如:

USE XXXX
SELECT ID, DESCRIPTION,STATUS
FROM PART
WHERE 
PART.ID LIKE 'PCH%'
AND PART.DESCRIPTION NOT LIKE '%OBSOLETE%'
AND (PART.STATUS <> 'O' OR PART.STATUS IS NULL)

这是一个小例子。想象一下这是你的桌子,你正在发布你的声明WHERE PART.STATUS &lt;&gt; 'O'

PART(STATUS)
'A'
'O'
NULL

计算结果为:

WHERE 'A' <> 'O' --TRUE
WHERE 'O' <> 'O' --FALSE
WHERE NULL <> 'O'--UNKNOWN

由于WHERE 子句仅返回谓词结果为TRUE 的行,因此您将在此处仅获得“A”。

【讨论】:

  • 是的,即使 null = null 也不是 true :) SQL Null 的维基百科页面总是有助于深入讨论
  • @Andomar,是的,应该有at least one side of predicate is NULL。已编辑。
【解决方案2】:

这里的问题在于nullvalue,因为与它的每个逻辑比较都会返回 false,例如

PART.STATUS = NULL-- Would be false
PART.STATUS <> NULL-- would also return false

所以你应该像这样进行比较

AND (PART.STATUS <> 'O' OR PART.STATUS IS NULL)

【讨论】:

    【解决方案3】:

    您缺少的部分是NULL 不是一个值,而是它的absenceNULL 表示该字段中的值不存在或未知。这就是为什么您不能直接将值与NULL 进行比较。如其他答案所述,您必须使用PART.STATUS IS NULL。另一种选择是使用ISNULL 函数,它将测试NULL 的值,如果是,将返回您在第二个参数上指定的任何值。例如

    USE XXXX
    SELECT ID, DESCRIPTION,STATUS
    FROM PART
    WHERE 
    PART.ID LIKE 'PCH%'
    AND PART.DESCRIPTION NOT LIKE '%OBSOLETE%'
    AND ISNULL(PART.STATUS, '') <> 'O'
    

    查看NULL in Sql ServerISNULL 函数的文档。另外,this question 可能有用。

    【讨论】:

    • 但您可以直接将null 与一个值进行比较。结果将是unknown。不确定“该字段不存在或未知”是什么意思。 null 业务很奇怪,没有引入 null 的类型:)
    • 好吧,只要你能写[some value] = null,当然你也可以比较一个值到一个null...但结果总是unknown为你说。是的,null 本身就是一个完整的逻辑,我只是​​想改写文档所说的内容。我认为是其中一种想法,每个人都可以大致了解,但永远不会真正理解它在引擎盖下的作用。
    • 当您阅读Wikipedia article 时,您会理解它(或者至少,这对我有用。)这两个问题是unknown 的存在与true 处于同一级别或falsenull 是一个值,unknown 是表达式的结果。 where null = 1where unknown 在概念上有效,但 where nullwhere unknown = 1 无效。
    【解决方案4】:
    USE XXXX
    SELECT ID, DESCRIPTION,STATUS
    FROM PART
    WHERE 
    PART.ID LIKE 'PCH%'
    AND PART.DESCRIPTION NOT LIKE '%OBSOLETE%'
    OR PART.STATUS != 'O'
    

    【讨论】:

    • 解释这与问题中发布的代码有何不同。我必须读四遍才能看到它!
    • @GlennRanders-Pehrson:在问题中他使用了AND PART.STATUS != 'O',而在我的回答中我使用了or
    【解决方案5】:

    也许您的误解可能是关于 NULL 概念。 NULL 不是空字符串,与 'O' 没有区别,它只是 NULL

    这就是你必须使用的原因

    AND PART.STATUS IS NULL
    

    AND isnull(PART.STATUS, '') <> 'O'
    

    【讨论】:

      【解决方案6】:

      记住 NULL 在数据库中的处理方式很重要。这根本不是一个值!

      没有运算符 (>,

      用 SQL 写“where column = NULL”就像是在说“给我所有值不是值的行

      【讨论】:

        【解决方案7】:

        Null 值不能与等于 (=) 或不等于运算符进行比较。试试下面的:

        USE XXXX
        SELECT ID, DESCRIPTION,STATUS FROM PART WHERE 
        PART.ID LIKE 'PCH%'
        AND PART.DESCRIPTION NOT LIKE '%OBSOLETE%'
        AND ISNULL(PART.STATUS, '') <> 'O'
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-08-29
          • 2021-12-17
          • 1970-01-01
          • 1970-01-01
          • 2015-10-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多