SQL Server 中不等于运算符不返回 NULL 值

lif*_*ney 3 null sql-server query

我有以下查询,我正在查找该列不等于 1 的任何行istrue。但结果只包含 0 的记录,忽略 null 的记录。虽然我知道使用(istrue != 1 or istrue is null)会产生预期的结果,但我很好奇导致 SQL Server 排除 null 值的底层机制。您能否提供对此行为的见解?谢谢!

create table #test
(
id int,
val varchar(100),
istrue bit
)

insert into #test values 
(1, 'test-1', 1),
(2, 'test-2', 0),
(3, 'test-3', 1),
(4, 'test-4', 0),
(5, 'test-5', null),
(6, 'test-6', null)

select * from #test
where istrue != 1

drop table if exists #test
Run Code Online (Sandbox Code Playgroud)

Yan*_*tle 19

考虑检查文档

NULL 表示该值未知。空值与空值或零值不同。没有两个空值是相等的。两个空值之间或空值与任何其他值之间的比较将返回未知,因为每个 NULL 的值都是未知的。

  • 当然,根本问题是 ANSI/SQL 标准误用了 _null_ 这个词,它并不意味着“未知”或“不可知”,而是“空/空白/无效”。根据单词的含义,列为空的预期含义是“该值故意留空/空/未填充(但其值并非未知)”。但事实并非如此,我们陷入了一种不直观的定义,从而导致了像这样的错误和问题。 (4认同)

J.D*_*.D. 7

除了已经说过的之外,这不仅仅是 SQL Server 实现,而且遵循 ANSI 标准,因此其他数据库系统也有类似的行为。

如果您确实想以相同的方式对待NULL值并且其中一个值是变量或文字,那么您可以做的一件事是在运行查询之前NULL关闭逻辑ANSI_NULL

设置 ANSI_NULLS 关闭;

这将适用于会话级别。这是dbfiddle.uk 的示例

但不幸的是,这对您的示例情况没有帮助,因为您试图将NULL非空文字的位置进行比较。

在您的情况下,您必须明确检查IS NULL列,正如您所提到的,或者您可以使用诸如ISNULL()包装列之类的函数并提供有意义的替换值。例如:ISNULL(istrue, 0) != 1


Mar*_*ith 6

istrue如果您认为在这种情况下的值是未知的NULL,那么它可能等于也可能不等于1

istrue != 1然后表达式的计算结果为unknown

SQL 仅返回子句WHERE计算结果为 的行true

如果您使用的是 SQL Server 2022+,您可以使用

WHERE istrue IS DISTINCT FROM 1
Run Code Online (Sandbox Code Playgroud)

给出您想要的不等式语义(Fiddle)。