为什么Sql条件(not in,not like,!=)在表的varchar值上不起作用

isl*_*din 3 sql sql-server sql-server-2008

我有一个包含两列并包含两个记录的表。

SQL表结构:

CREATE TABLE #TEMP_TEST
(
    ID bigint NOT NULL,
    DESCRIPTION varchar(500) NULL
) ON [PRIMARY]

INSERT INTO #TEMP_TEST VALUES(1, 'obsolete')
INSERT INTO #TEMP_TEST VALUES(2, NULL)

SELECT * FROM #TEMP_TEST
Run Code Online (Sandbox Code Playgroud)

#TEMP_TEST表中的虚拟记录总数

ID      | DESCRIPTION |
--------+-------------+
1       | obsolete    |
2       | NULL        |
Run Code Online (Sandbox Code Playgroud)

查询这些条件=likein工作正常。

SELECT * FROM #TEMP_TEST LC2 WHERE LC2.DESCRIPTION ='obsolete'
SELECT * FROM #TEMP_TEST LC2 WHERE LC2.DESCRIPTION LIKE 'obsolete'
SELECT * FROM #TEMP_TEST LC2 WHERE LC2.DESCRIPTION IN ('obsolete')
Run Code Online (Sandbox Code Playgroud)

这些结果正常工作:

ID      | DESCRIPTION |
--------+-------------+
1       | obsolete    |
Run Code Online (Sandbox Code Playgroud)

问题

查询这些条件!=not likenot in不能正常工作。

SELECT * FROM #TEMP_TEST LC2 WHERE LC2.DESCRIPTION != 'obsolete'
SELECT * FROM #TEMP_TEST LC2 WHERE LC2.DESCRIPTION NOT LIKE 'obsolete'
SELECT * FROM #TEMP_TEST LC2 WHERE LC2.DESCRIPTION NOT IN ('obsolete')
Run Code Online (Sandbox Code Playgroud)

结果:

ID      | DESCRIPTION |
--------+-------------+
Run Code Online (Sandbox Code Playgroud)

预期成绩:

ID      | DESCRIPTION |
--------+-------------+
2       | NULL        |
Run Code Online (Sandbox Code Playgroud)

我应该怎么做才能获得预期的结果?

如果需要进一步的条件以取得预期的结果,请检查并给出所需的答案或评论。

Gio*_*uri 5

这是由于SQL Server中的三个有价值的逻辑。谓词可以评估为:

  • 真正
  • 未知

在SQL Server中比较数据时,应始终考虑可能NULL的。考虑以下谓词:

where 1=1 => evaluates to true
where 2=1 => evaluates to false
where 1=null => evaluates to unknown
where null=null => evaluates to unknown
Run Code Online (Sandbox Code Playgroud)

所以,比较NULL为任意值,即使NULL计算结果为UNKNOWN . Now you should know howWHERE clause works. It returns rows where predicate evaluates to只TRUE`!

就您而言,谓词:

WHERE  LC2.DESCRIPTION != 'obsolete'
Run Code Online (Sandbox Code Playgroud)

将评估为:

obselete != obselete => false
obselete != null => unknown
Run Code Online (Sandbox Code Playgroud)

因此,谓词不会求值到任何行,因此TRUE您不会得到任何结果。

关于应该做什么的问题,可以执行以下操作:

WHERE ISNULL(LC2.DESCRIPTION, 'not absolete') != 'obsolete'
Run Code Online (Sandbox Code Playgroud)

但是在这里您的谓词SARG无法使用,如果为LC2.DESCRIPTION列创建了索引,那么您将不会从索引中受益。

标准方法是使用OR

WHERE LC2.DESCRIPTION != 'obsolete' OR LC2.DESCRIPTION IS NULL 
Run Code Online (Sandbox Code Playgroud)