我有以下查询,我正在查找该列不等于 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
考虑检查文档:
istrue
如果您认为在这种情况下的值是未知的NULL
,那么它可能等于也可能不等于1
。istrue != 1
然后表达式的计算结果为unknown
SQL 仅返回子句
WHERE
计算结果为 的行true
。如果您使用的是 SQL Server 2022+,您可以使用
给出您想要的不等式语义(Fiddle)。
使用不等于运算符 (<>) 或不等运算符 (!=) 时,SQL Server 不会返回 NULL,因为 NULL 不是可以与其他值进行比较的值。
NULL 表示未知或缺失值,因此与 NULL 的任何比较都会导致未知或错误
因此,如果要在查询结果中包含 NULL,除了不等于运算符之外,还需要使用 IS NULL 谓词
除了已经说过的之外,这不仅仅是 SQL Server 实现,而且遵循 ANSI 标准,因此其他数据库系统也有类似的行为。
如果您确实想以相同的方式对待
NULL
值并且其中一个值是变量或文字,那么您可以做的一件事是在运行查询之前NULL
关闭逻辑ANSI_NULL
:这将适用于会话级别。这是dbfiddle.uk 的示例。
但不幸的是,这对您的示例情况没有帮助,因为您试图将列与
NULL
非空文字的位置进行比较。在您的情况下,您必须明确检查
IS NULL
列,正如您所提到的,或者您可以使用诸如ISNULL()
包装列之类的函数并提供有意义的替换值。例如:ISNULL(istrue, 0) != 1