表中的NULL值自我比较


13

我总是对某些神秘的t-sql行为感到困惑,如下所示

-- Create table t and insert values.  
use tempdb
CREATE TABLE dbo.t (a INT NULL);  
-- insert 3 values
INSERT INTO dbo.t values (NULL),(0),(1);  
GO  
set ansi_nulls off -- purposely turn off, so we can allow NULL comparison, such as null = null
go
-- expect 3 rows returned but only 2 returned (without null value row)
select * from dbo.t where a = a 

这与如何检索表中的所有行无关,也与避免使用ANSI_NULLS无关。

我只想征集一些见解,以了解为什么t-sql会如此表现。

Answers:


13

这是令人惊讶的行为,但是从MSDN页面SET ANSI_NULLS,我们至少可以知道这是预期的行为。永远不要使用的另一个原因ANSI_NULLS OFF

SET ANSI_NULLS仅当比较的操作数之一为NULL或时 ,才影响比较NULL如果比较的两面都是列或复合表达式,则该设置不会影响比较。


8

尽管从msdn文档中可能不清楚,但我相信您会发现以下事实

“仅当比较操作数之一是NULL变量或文字NULL时,SET ANSI_NULLS ON才会影响比较。如果比较的两面都是列或复合表达式,则该设置不会影响比较。”

看到这个/programming/2866714/how-does-ansi-nulls-work-in-tsql


谢谢Scott和ypercube,您的回答都是针对此行为的要点,因此,我对您的回答都表示赞同。
jyao

Ypercube排名第一:)
Scott Hodgin '16

4

罗伯特·谢尔顿(Robert Sheldon)在2015年的以下文章中讨论了NULL行为及其为何有时(但并非总是)失败的原因

https://www.simple-talk.com/sql/t-sql-programming/how-to-get-nulls-horribly-wrong-in-sql-server/

他描述了13个NULL故障,程序员可以轻松地解决这些故障。

失败#1:不知道NULL意味着什么

说明:NULL是一个非值,一个不存在的值。不为零。它不是一个空字符串。值不能等于NULL。没有两个NULL值相等

这是基本问题,但请务必阅读其他故障。

是的,早期版本(我相信SQL Server 7之前的版本)的行为有所不同,更像您想要的。

但是,如果您在Stack Overflow和Stack Exchange上搜索问题,则会发现许多讨论该问题的长线程。


3
我曾经阅读过Robert Sheldon的链接文章,但是(IMHO)没有任何理论或证据可以解释我的示例的行为。
jyao

1
“没有两个NULL值相等。” 可以,但是即使知道的人在将ansi nulls设置为off时也会期望相反。特别是因为WHERE NULL = NULL设置为时会产生true。
ypercubeᵀᴹ

1

为了增加讨论的意义,可以对SQL92标准的NULL定义进行模棱两可的解释。这是来自sqlite.org的各种DBMS 的NULL处理和解释良好总结

披露:我还记得从上面链接的sqlite.org页面的较旧版本(如6-8年前)中读到的关于SQL92的“歧义”,但是此后此页面已被更新。

RLF的上述答案引用得很好,但是如果我不同意Robert Sheldon,那仅仅是因为我认为“不存在的东西”(即NULL)在哲学上和英语-语义上等同于“ 其他不存在的东西” ”。如果我想了解谢尔顿的逻辑,那么可以声明NULL的定义也是 NULL。(如果它不存在,那么我们如何定义它?令人毛骨悚然,是吧?)

我看到的变化罗素悖论酿酒(头痛)。:-\

但这又是关于英语语义NOT SQL)的讨论,哲学辩论就在这里。:-)


PS我是这个SE社区的新成员。如果这已经讨论广告nauseum之前,那么我道歉。
pr1268

1
标准中的歧义到底在哪里?
ypercubeᵀᴹ

@ypercubeᵀᴹ:我相信歧义在于试图将3VL “拟合” 为布尔值。具有NULL比较的表联接可以用几种不同的方式来解释。
pr1268 '16

我会同意不一致,但不会歧义。
ypercubeᵀᴹ

1
@ypercubeᵀᴹ:很公平……我只是引用上面链接的sqlite.org页面的旧版本所说的内容(“ SQL92在NULL处理和解释方面是模棱两可的”或类似的东西)。但是我并不是要争论。也许sqlite.org页面本身具有误导性和/或全盘错误。这可能解释了为什么更新它。
pr1268 '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.