为什么NULL = NULL在SQL Server中评估为false


146

在SQL Server中,如果 nullParam=NULL在where子句中,则其总值为false。这是违反直觉的,并导致了我很多错误。我确实了解IS NULLIS NOT NULL关键字是正确的方法。但是,为什么SQL Server会表现这种方式?


166
我没有姐姐,我的朋友也没有。如果“ NULL = NULL”,那么我们有一个共同的姐妹,因此是相关的!:)
马特·汉密尔顿

11
关于SQL NULL的争议长期存在(例如,请参见:en.wikipedia.org/wiki/Null_%28SQL%29#Controversyfirstsql.com/inulls.htm)。这里的特定点是,平等是一个由来已久的数学概念,SQL违反了它-平等是自反的:对于每个x,x = x。这必须始终是正确的,否则,人们会引入一种对平等的解释,这不是标准的,混乱是显而易见的结果。
MaD70

14
它根本不违反数学。我在想两个数字。我不会告诉你它们是什么。所以,现在您告诉我,它们相等吗?
Tom H

10
@马特,我不同意你的比喻。NULL = NULL并不意味着您有一个共同的姐妹,这意味着您俩都缺少一个姐妹。
reustmd 2010年

5
@ manu08不,当前的实现(NULL从不等于NULL)意味着我们俩都缺少姐妹,这就是我的观点。
马特·汉密尔顿

Answers:


205

在这种情况下,请将null视为“未知”(或“不存在”)。在任何一种情况下,您都不能说它们相等,因为您不知道它们的价值。因此,null = null的计算结果不为true(false或null,具体取决于您的系统),因为您不知道这些值是否相等。此行为在ANSI SQL-92标准中定义。

编辑:这取决于您的ansi_nulls设置。如果您关闭ANSI_NULLS,则此值将为true。运行以下代码作为示例...

set ansi_nulls off

if null = null
    print 'true'
else
    print 'false'


set ansi_nulls ON

if null = null
    print 'true'
else
    print 'false'

11
x = x仅在x是已知值时成立。NULL是未知值的文本表示形式。如果您有两个未知值,则不能确定地说出它们的相等性。我相信这已经适用了几个世纪。
Dewayne Christensen

4
由于是十二月,所以我们以一个季节性的例子为例。我在树下有两个礼物。现在,你告诉我我是否有两个相同的东西。
Dewayne Christensen

5
SQL NULL与IEEE浮点NaN也没有什么不同(NaN == NaN) == false && (NaN != Nan) == false && (NaN < NaN) == false && ...-因为,如果不是数字,那么就不能多说了。这是未知的。这个概念是合理的,即使对于从未见过的人来说都是不直观的。
帕维尔·米纳夫

8
这里没有违反自反性,因为NULL不是值集(域,在关系术语中)的成员。NULL 不是值。它是未知值的占位符。
帕维尔·米纳夫

9
换句话说,NULLSQL表达式中的每个表达式都可以视为一个不同的数学变量。因此,表达式NULL = NULL应视为x = y,其中xy是未绑定变量。现在,如果有人问您,的值是x = y多少?唯一合理的答案是“一些z”。因此,我们有(x = y) = z-或将其转录回SQL的方法(NULL = NULL) = NULL
帕维尔·米纳夫

130

弗兰克几岁了?我不知道(空)。

雪莉几岁?我不知道(空)。

弗兰克和雪莉年龄相同吗?

正确答案应该是“我不知道”(空),而不是“不”,因为弗兰克和雪莉可能是同一年龄,我们根本不知道。


4
我不同意null表示“未知”。它实际上意味着“没有数据”。这可以用来表示未知信息的情况,但是实际上它更有可能用来表示某些东西不存在。继续您的示例:弗兰克的中间名是什么?他没有一个(空)。雪莉(Shirley)的中间名是什么?她没有一个(空)。弗兰克和雪莉有相同的中间名吗?是?没有?不知道吗 我可以看到一个参数为“否”,也可以看到一个参数为“不知道”,但是没有真正的参数为“是”,除非您过于直白。
Richiban

2
@richiban我不同意。缺少一行就意味着“没有数据”
Neil McGuigan

1
@NeilMcGuigan如果具有自己的表的数据是正确的,那么列中表示的数据又如何呢?您不会使用“空”来表示数据不存在的事实吗?“未知”是缺少数据的非常具体的原因。
Richiban

3
但是null = null产量FALSE却不是NULL
slartidan

1
@slartidan我同意你的观点,但是那是不正确的
Neil McGuigan

28

我希望在这里阐明我的立场。

认为NULL = NULLFALSE是错误的。黑客和先生正确回答NULL。这就是为什么。戴维·克里斯滕森(Dewayne Christensen)在给斯科特·艾维Scott Ivey)的评论中写信给我:

由于是十二月,所以我们以一个季节性的例子为例。我在树下有两个礼物。现在,你告诉我我是否有两个相同的东西。

它们可以是不同的,也可以是相等的,直到一个打开同时出现时才知道。谁知道?您邀请了两个彼此都不认识并且都向您做过相同礼物的人-罕见,但并非不可能§

那么问题来了:这两个UNKNOWN呈现的是否相同(等于=)?正确答案是:未知(即NULL)。

本示例旨在说明 “ ..(falsenull,取决于您的系统)..”是正确的答案-并非如此,只有 NULL在3VL中才是正确的(或者您可以接受给出错误答案的系统吗? )

对这个问题的正确答案必须强调以下两点:

  • 三值逻辑(3VL)是违反直觉的(请确保在Stackoverflow和其他论坛上查看关于此主题的无数其他问题);
  • 基于SQL的DBMS甚至不尊重3VL,有时会给出错误的答案(就像最初的声明那样,SQL Server在这种情况下会这样做)。

因此,我重申:SQL并不能很好地强迫人们解释相等的反身性质,该性质表明:

for any x, x = x §§(用通俗的英语说:无论话语领域如何,“事物”始终等于自身)。

..在3VL( ,TRUE,)。FALSE NULL人们的期望符合2VL(TRUEFALSE即使在SQL中也对所有其他值都有效),即对于x的任何可能值x = x 始终取为 TRUE,无例外。

还请注意,NULL是有效的“ 非值 ”(因为其辩护者假装为),可以将其指定为关系变量的一部分的属性值(??)。因此,它们不仅是逻辑表达式类型的所有类型(域)的可接受值。

这是我的观点NULL作为价值,是一个“奇怪的野兽”。没有委婉的说法,我更愿意说:胡说八道

我认为这种表述更加清晰和值得商--对我英语水平不佳表示抱歉。

这仅仅是一个的空值的问题。如果可能,最好完全避免使用它们。

§我们在这里关注,因此两个礼物总是两个不同的物理对象这一事实不是有效的反对;如果您不确信我很抱歉,这里不是解释值和“对象”语义之间差异的地方(关系代数从一开始就具有值语义-请参阅Codd的信息原理;我认为某些SQL DBMS实现者没有甚至不在乎常见的语义)。

§§据我所知,这是自古代以来就接受的一种公理(以一种形式或另一种形式,但始终以2VL解释),而这正是因为如此直观。3VL(实际上是逻辑系列)是最近的开发(但我不确定何时首次开发)。

旁注:如果有人将BottomUnitOption Type 引入作为证明SQL NULL合理性的尝试,那么只有在进行了相当详细的检查之后,我才会相信我,这将显示具有NULL的SQL实现如何具有健全的类型系统,并最终阐明,真正的NULL是什么(这些“值不等于值”)。


接下来,我将引用一些作者的话。任何错误或遗漏可能都是我的,而并非原始作者。

Joe Celko关于SQL NULL

我看到Joe Celko在该论坛上经常被引用。显然他是这里一位备受尊敬的作家。因此,我对自己说:“他写了什么有关SQL NULL的文章?他如何解释NULL带来的许多问题?”。我的一个朋友拥有Joe Celko的SQL的电子书版本,该版本是关于聪明人的:高级SQL编程,第三版。让我们来看看。

首先是目录。最让我印象深刻的是在最不同的情况下提到NULL的次数:

3.4算术和NULL 109
3.5往返于NULL的值110
3.5.1 NULLIF()函数110
6 NULL:SQL 185中的数据丢失
6.4比较NULL 190
6.5 NULL和逻辑190
6.5.1 NULL在子查询谓词191
6.5.2中SQL解决方案193
6.6数学和NULL 193
6.7函数和NULL 193
6.8 NULL和主机语言194
6.9 NULL的设计建议195
6.9.1从主机程序中避免NULL 197
6.10有关多个NULL值的说明198
10.1 IS NULL谓词241
10.1。 1 NULL的来源242
...

等等。它给我敲响了“讨厌的特例”。

在本书中,我将摘录其中一些案例,出于版权方面的考虑,试图将自己局限于基本内容。我认为这些报价属于“合理使用”原则,甚至可以刺激人们购买该书-因此,我希望没有人会抱怨(否则,即使不是全部,我也要删除其中的大部分内容)。此外,出于相同的原因,我将避免报告代码片段。对于那个很抱歉。购买该书以了解有关数据推理的知识。

括号之间的页码如下。

非空约束(11)

最重要的列约束是NOT NULL,它禁止在列中使用NULL。定期使用此约束,只有在有充分理由时才将其删除。对数据进行查询时,它将帮助您避免NULL值的复杂性。

这不是价值 ; 它是一个标记,用于保存可能存在值的位置。

同样,这种“有价值但不完全有价值”胡说八道。其余的对我来说似乎很明智。

(12)

简而言之,NULL会在SQL中引起很多不规则的功能,我们将在后面讨论。最好的选择是记住无法避免的情况和NULL规则。

SQL,NULL和无限的用法:

(104)第3章:SQL中的数值数据

由于多种原因,SQL尚未接受IEEE数学模型。

...

如果SQL中允许使用IEEE数学规则,那么我们将需要无限的类型转换规则以及一种在转换后表示无限精确数值的方法。人们对NULL有足够的麻烦,所以我们不要去那里。

SQL实现尚未确定NULL在特定上下文中的真正含义:

3.6.2指数函数(116)

问题是(x <= 0)时对数不确定。一些SQL实现返回一条错误消息,一些返回NULL和DB2 / 400。其版本3版本1返回* NEGINF(“负无穷大”的缩写)。

Joe Celko引用David McGoveran和CJ日期:

6 NULL:SQL中缺少数据(185)

David McGoveran和CJ Date 在他们的《 Sybase和SQL Server指南》一书中说:“作者认为,比NULL(至少目前在SQL中已定义和实现)比NULL麻烦得多,应避免,应避免。它们显示出非常奇怪和不一致的行为,并且可能是错误和混乱的丰富来源。(请注意,这些评论和批评适用于支持SQL样式NULL的任何系统,而不仅限于SQL Server。)”

NULL作为吸毒成瘾

(186/187)

在本书的其余部分中,我会敦促您不要使用它们,这似乎是矛盾的,但事实并非如此。将NULL视为毒品;正确使用它会为您工作,但是滥用它可能会毁了一切。最好的策略是在可能的情况下避免NULL,并在必要时正确使用它们。

我在这里的唯一反对意见是“正确使用它们”,这与特定的实现行为严重地相互作用。

6.5.1子查询谓词中的NULL(191/192)

人们忘记了子查询经常隐藏带有NULL的比较。考虑以下两个表:

...

结果将为空。这是违反直觉的,但却是正确的。

(分隔器)

6.5.2标准SQL解决方案(193)

SQL-92通过添加以下形式的新谓词解决了一些3VL(三值逻辑)问题:

<搜索条件> IS [否]是| 假| 未知

但是UNKNOWN本身就是问题的根源,因此下文引用的CJ Date在第4.5章中推荐在SQL中避免空值

  • 请勿在任何情况下使用关键字UNKNOWN。

阅读UNKNOWN上的“ ASIDE”,该链接也在下面链接。

6.8 NULL和主机语言(194)

但是,您应该知道必须将NULL传递给主机程序时如何处理它们。没有定义嵌入的标准宿主语言不支持NULL,这是避免在数据库模式中使用它们的另一个很好的理由。

(分隔器)

6.9 NULL的设计建议(195)

最好在所有列上声明所有基表都具有NOT NULL约束。NULL使不懂SQL的人感到困惑,并且NULL代价很高。

反对意见:NULL甚至会使熟知SQL的人感到困惑,请参阅下文。

(195)

在外键中应避免为NULL。SQL允许这种“疑问的好处”关系,但是它可能导致涉及联接的查询中的信息丢失。例如,给定库存中的零件号代码,而Orders表将其称为FOREIGN KEY,则获取具有NULL的零件清单时将遇到问题。这是强制性关系;您不能订购不存在的零件。

(分隔器)

6.9.1避免主机程序中的NULL(197)

您可以避免使用某些编程规则将NULL从主机程序放入数据库中。

...

  1. 确定丢失的数据对编程和报告的影响: 带NULL的数字列是一个问题,因为使用聚合函数的查询可能会产生误导性的结果。

(分隔器)

(227)

空集的SUM()始终为NULL。使用此技巧时,最常见的编程错误之一是编写可能返回多个行的查询。如果您没有考虑,您可能将最后一个示例写为:...

(分隔器)

10.1.1 NULL的来源(242)

重要的是要记住在哪里可以出现NULL。它们不仅仅是列中的可能值。空集上的聚合函数,OUTER JOIN,带有NULL的算术表达式以及OLAP运算符均返回NULL。这些构造通常在VIEW中显示为列。

(分隔器)

(301)

当您尝试将IN谓词转换为EXISTS谓词时,会发现NULL的另一个问题。

(分隔器)

16.3 ALL谓词和极值函数(313)

首先,这两个谓词在SQL中是不同的,这与直觉相反:

...

但是,您必须记住极值函数的规则-在返回较大或最小值之前,它们会丢弃所有NULL。ALL谓词不会丢弃NULL,因此您可以在结果中获取它们。

(分隔器)

(315)

但是,标准中的定义用否定词表示,因此NULL带来了疑问。...

如您所见,最好避免在UNIQUE约束中使用NULL。

讨论GROUP BY:

将NULL视为彼此相等,并形成自己的组。然后,将每个组缩小为新结果表中的一行,以替换旧的结果表。

这意味着对于GROUP BY子句,NULL = NULL不会像3VL中那样评估为NULL,而是评估为TRUE。

SQL标准令人困惑:

ORDER BY和NULL(329)

是否将排序键值NULL视为大于或小于非NULL值是实现定义的,但是...

...有一些SQL产品可以做到这两种方式。

在1999年3月,克里斯·法拉尔(Chris Farrar)从他的一位开发人员那里提出了一个问题,促使他研究了我认为我理解的SQL标准的一部分。克里斯发现规范的一般理解与实际措词之间存在一些差异

等等。我认为Celko够了。

SQL NULL上的CJ日期

CJ Date关于NULL更彻底:避免在SQL句点中使用NULL。实际上,他的SQL和关系理论的第4章:如何编写准确的SQL代码标题为“没有重复,没有NULL”,其子章“ 4.4 NULL有 什么问题?” 和“ 4.5在SQL中避免为空”(链接:感谢Google Books,您可以在线阅读某些页面)。

Fabian Pascal关于SQL NULL

从其数据库管理中的实际问题-思维从业者的参考(网上未摘录,对不起):

10.3实际含义

10.3.1 SQL空值

... SQL受3VL固有的问题以及许多怪癖,复杂性,违反直觉和彻底错误的困扰[10,11];其中包括:

  • 聚合函数(例如SUM(),AVG())将忽略NULL(COUNT()除外)。
  • 没有行的表上的标量表达式的计算结果错误地为NULL,而不是0。
  • 表达式“ NULL = NULL”的计算结果为NULL,但在SQL中实际上无效;但是ORDER BY将NULL视为相等(无论它们在“常规”值之前还是之后,都留给DBMS供应商)。
  • 表达式“ x IS NOT NULL”不等于“ NOT(x IS NULL)”,与2VL中的情况一样。

...

所有商业实现的SQL方言都遵循这种3VL方法,因此,它们不仅解决了这些问题,而且还存在具体的实现问题,具体问题因产品而异


4
“这就是我的观点:NULL作为值是“奇怪的野兽”。” -那是因为NULL没有价值。
帕维尔·米纳夫

1
另外,SQL Server不提供(NULL = NULL) -> FALSE。引用文档的内容ANSI_NULLS:“当指定为ON时,所有与空值的比较都将得出UNKNOWN。当指定了OFF时,如果两个值都为NULL,则将非UNICODE值与空值的比较都
将为

@Pavel Minaev:a)TRUE比FALSE好吗?b)如果不是值,为什么将其分配为变量值的一部分?
MaD70

1
>>因为它是十二月,所以我们以一个季节性的例子为例。我在树下有两个礼物。现在,你告诉我我是否有两个相同的东西。.....是的,您做了两件事,就您所关注的而言,就您目前所知,它们与您完全相同
Brad Thomas

3
null = null应该为true。null被良好定义的其可值表示一个未知值,但它也可表示不存在的值。开发人员应自行决定null代表什么,但null本身绝对是一个值,null为null = null。任何其他实现都将带来灾难,因为您将三元逻辑插入到本质上是布尔值的谓词中。我很高兴这已经成为SQL Server中的永久设置。关关关它。
Triynko 2015年


9

仅仅因为您不知道什么是两件事,并不意味着它们是相等的。如果您想到NULL“ NULL”(字符串),那么您可能想要一个不同的相等性测试,例如Postgresql的IS DISTINCT FROMANDIS NOT DISTINCT FROM

来自PostgreSQL文档“比较函数和运算符”

表达式IS DISTINCT FROM表达式

表达式IS NOT DISTINCT FROM表达式

对于非空输入,IS DISTINCT FROM<>运算符相同。但是,如果两个输入均为null,则返回false,如果只有一个输入为null,则返回true。类似地,IS NOT DISTINCT FROM=非空输入相同,但是当两个输入均为空时,它返回true,而只有一个输入为空时,它返回false。因此,这些构造有效地充当空值是正常数据值,而不是“未知”。


5

至少可以说,NULL的概念值得怀疑。Codd在上下文中介绍了关系模型和NULL的概念(并提出了不止一种NULL!)。但是,关系理论自Codd的原始著作以来就已经发展起来:他的一些提议此后被舍弃(例如主键)其他人(例如theta运算符)从未流行。在现代关系理论(我应该强调的是真正的关系理论)中,NULL根本不存在。参见第三宣言。http://www.thethirdmanifesto.com/

SQL语言存在向后兼容的问题。NULL进入了SQL,我们一直坚持下去。可以说,NULLSQL的实现存在缺陷(SQL Server的实现由于其ANSI_NULLS选项而使事情变得更加复杂)。

我建议避免在基表中使用NULLable列。


尽管也许我不应该被吸引,但我只是想断言自己对NULLSQL的工作方式的更正:

NULL= NULL计算为UNKNOWN

UNKNOWN 是一个逻辑值。

NULL 是一个数据值。

这很容易证明,例如

SELECT NULL = NULL

在SQL Server中正确生成错误。如果结果是一个数据值,那么我们期望看到NULL,正如这里的一些答案(错误地)表明我们会那样。

UNKNOWN分别在SQL DML和SQL DDL中对逻辑值进行不同的处理。

在SQL DML中,UNKNOWN导致从结果集中删除行。

例如:

CREATE TABLE MyTable
(
 key_col INTEGER NOT NULL UNIQUE, 
 data_col INTEGER
 CHECK (data_col = 55)
);

INSERT INTO MyTable (key_col, data_col)
   VALUES (1, NULL);

INSERT成功此行,即使CHECK条件解析NULL = NULL。这是由于在SQL-92(“ ANSI”)标准中定义的:

11.6表约束定义

3)

如果表约束是检查约束定义,则令SC为紧接在约束约束定义中的搜索条件,令T为包含在相应表约束描述符中的表名。当且仅当不满足表约束

存在(选择*从哪里(SC))

是真的。

按照逻辑再次仔细阅读。

用简单的英语来说,我们在上面的新行中给出了关于存在UNKNOWN和被允许通过的“疑问的好处” 。

在SQL DML中,WHERE子句的规则更容易遵循:

搜索条件应用于T的每一行。where子句的结果是T的那些行的表,这些条件的搜索条件的结果为true。

用简单的英语将评估UNKNOWN结果中的行从结果集中删除。


5

technet上,有一个很好的解释说明空值如何工作。

Null表示未知。

因此布尔表达式

值=空

不会计算为false,而是计算为null,但是如果这是where子句的最终结果,则不会返回任何内容。这是一种实用的方法,因为很难想象返回null。

了解以下内容非常有趣且非常重要

如果在查询中

where (value=@param Or @param is null) And id=@anotherParam

  • 值= 1
  • @param为空
  • id = 123
  • @ anotherParam = 123

然后

“ value = @ param”评估为null
“ @param为null”评估为true
“ id = @ anotherParam”评估为true

因此要评估的表达式变为

(null或true)和true

我们可能会倾向于认为这里的“ null或true”将被评估为null,因此整个表达式将变为null,并且该行将不返回。

事实并非如此。为什么?

因为“ null Or true”的计算结果为true,这是非常合逻辑的,因为如果一个操作数对Or运算符为true,则无论另一个操作数的值如何,该操作都将返回true。因此,另一个操作数未知(空)并不重要。

因此,我们最终有了true = true,因此将返回该行。

注意:使用“ null或true”评估为true相同的清晰逻辑,“ null And true”评估为null。

更新:
好的,只是为了使它完整,我也想在这里添加其余的内容,这与上面的内容相比非常有趣。

“ null或false”评估为null,“ null和false”评估为false。:)

当然,逻辑仍然像以前一样不言而喻。


4

因为NULL均值“未知值”和两个未知值不能相等。

因此,如果按照我们的逻辑,NULLN°1等于NULLN°2,那么我们必须以某种方式告知:

SELECT 1
WHERE ISNULL(nullParam1, -1) = ISNULL(nullParam2, -1)

其中已知值-1N°1等于-1N°2


nullParam1 = -1nullParam2 =NULL空降事故..应该是ISNULL(NULLIF(@nullParam1, @nullParam2), NULLIF(@nullParam2, nullParam1)) IS NULL
Selvin

4

答案似乎都是从CS的角度出发的,所以我想从开发人员的角度来补充。

对于开发人员,NULL非常有用。这里的答案说NULL表示未知,也许在CS理论中是正确的,不记得了,已经有一段时间了。但是,在实际开发中,至少以我的经验来看,这种情况发生的时间约为1%。其余的99%用于值不是UNKNOWN但未知的情况。

例如:

  • Client.LastPurchase,适用于新客户。这不是未知数,已知他还没有购买。

  • 当将ORM与每个层次结构一起使用时,某些类的 某些值只是不被映射。

  • 映射树结构时,根通常会具有Parent = NULL

  • 还有很多...

我确定大多数开发人员在某个时候都写了WHERE value = NULL,没有得到任何结果,这就是他们学习IS NULL语法的方式。只要看看这个问题和相关链接有多少票即可。

SQL数据库是一种工具,应以最易于用户理解的方式设计它们。


1
每个人似乎都在喊“ NULL未知”,然后证明其行为合理。是的,如果这是前提,那么3VL也许是答案。但是在我工作的几乎所有数据库中,NULL都表示没有。抱歉,您的声音在旷野迷路了@AlexDev
John Rees

3

NULL不等于任何东西,甚至不等于本身。我个人了解NULL行为的解决方案是尽可能避免使用它:)。


1
可能等于一切,就如左/右/外连接一样……
Miguel Ventura 2009年

5
真是愚蠢的徒劳的答案。对于基本的代数孩子也可以说同样的话,但是如果没有真正意识到要解决的问题,它就会变得愚蠢而已。
埃文·卡罗尔

2
@Evan:实际上,避免NULL是一个好的解决方案。三值逻辑并非毫无争议,许多人认为没有NULL及其带来的所有(必要)复杂性,SQL会更好。
sleske 2010年

3
“很多人”是一个狡猾的人,“不容争议”是一种掩盖更简单的“有争议”的方法,而3VL则不是。
埃文·卡罗尔

“ NULL不等于任何东西,甚至不等于本身。” 按照这种逻辑,<somevalue>!= NULL应该返回true。但是,在SQL的怪异世界中,它是错误的。
汤姆·林特

3

问题:
一个未知等于另一个未知吗?
(NULL = NULL)
这个问题是没人能回答的,因此根据您的ansi_nulls设置,它的默认值为true或false。

但是问题
是:这个未知变量未知吗?
这个问题是完全不同的,可以正确回答。

nullVariable = null正在比较值
nullVariable为null正在比较变量的状态


3

混淆是由使用NULL引起的间接(抽象)级别引起的

回到“圣诞树下是什么”的类比,“未知”描述了有关框A中内容的知识状态。

因此,如果您不知道Box A中的内容,则说它是“未知”,但这并不意味着“ Unknown”位于该框中。盒子里有未知以外的东西,可能是某种物体,或者盒子里什么也没有。

同样,如果您不知道方框B中的内容,则可以将有关内容的知识状态标记为“未知”。

因此,这里有一个关键点:您对Box A的了解程度与您对Box B的了解程度相同。(在两种情况下,您的知识状态都是“未知”或“我不知道盒子里有什么”。)但是盒子中的内容可能相等,也可能不相等。

回到SQL,理想情况下,只有知道值之后才可以比较值。不幸的是,描述缺乏知识的标签存储在单元格本身中,因此我们很想将其用作值。但是我们不应该将其用作值,因为它会导致“当我们不知道Box A中的内容和/或我们不知道Box B中的内容时,Box A的内容等于Box B的内容。 (从逻辑上讲,“如果我不知道方框A中的内容,如果我不知道方框B中的内容,那么方框A中的内容=方框B中的内容”的含义是错误的。)

是的,死马。


3

MSDN上有一篇很好的描述性文章,介绍了null及其所引起的三种状态逻辑。

简而言之,SQL92规范将NULL定义为unknown,并且在以下运算符中使用的NULL会导致未初始化的结果意外:

= operator NULL   true   false 
NULL       NULL   NULL   NULL
true       NULL   true   false
false      NULL   false  true

and op     NULL   true   false 
NULL       NULL   NULL   false
true       NULL   true   false
false      false  false  false

or op      NULL   true   false 
NULL       NULL   true   NULL
true       true   true   true
false      NULL   true   false

但是问题不在于3VL(三值逻辑)是关于平等的反身性质。
MaD70

更确切地说,正如我在回答中最后详述的那样,当在3VL中解释平等时,就会出现问题,因此平等的反身性质并不总是等于true。
MaD70

1

null在sql中是未知的,因此我们不能期望两个未知数相同。

但是,您可以通过将ANSI_NULLS设置为Off(默认情况下为On)来实现该行为。您将可以使用=运算符表示null

SET ANSI_NULLS off
if null=null
print 1
else 
print 2
set ansi_nulls on
if null=null
print 1
else 
print 2

2
这是各种没有。世界有一个的定义null,学习理解它或只是更改表以具有int类型并更新列。
埃文·卡罗尔

3
我真的不建议关闭SET ANSI_NULLS。我很难找到有关ANSI_NULLS的信息。但是,总是很有趣的是,当遇到出现“ SomeId = null”的行时,特别了解所有可用选项,如果不了解ANSI_NULLS,您将如何理解该行。我的样子,我的帖子很有用.. :)
PS。

1

您为政府登记有关公民的信息工作。这包括该国每个人的身份证。大约40年前,一个孩子被留在教堂的门口,没人知道他们的父母是谁。此人的父亲ID为NULL。存在两个这样的人。计算与至少一个其他人(是兄弟姐妹的人)共享同一父亲ID的人。你也算这两个吗?

答案是否定的,你不是,因为我们不知道他们是否是兄弟姐妹。

假设您没有NULL选择,而是使用一些预定的值来表示“未知”,也许是一个空字符串或数字0或*字符,等等。那么您的查询中将带有* = * ,0 = 0和“” =“”等。这不是您想要的(按照上面的示例),而且您可能经常忘记这些情况(上面的示例是普通日常思维之外的一个清晰的例子) ),那么您需要为您记住的语言NULL = NULL是不正确的。

必要性是发明之母。


0

只是其他精彩答案的补充:

AND: The result of true and unknown is unknown, false and unknown is false,
while unknown and unknown is unknown.

OR: The result of true or unknown is true, false or unknown is unknown, while unknown or unknown is unknown.

NOT: The result of not unknown is unknown

0

如果您要查找一个返回两个NULL的true的表达式,则可以使用:

SELECT 1 
WHERE EXISTS (
    SELECT NULL
    INTERSECT
    SELECT NULL
)

如果要将数据从一个表复制到另一个表,这将很有帮助。


0

相等性测试(例如,在case语句中的when子句中)可以从

XYZ = NULL 

XYZ IS NULL

如果我想将空格和空字符串视为等于NULL,我通常也使用相等测试:

(NULLIF(ltrim( XYZ ),'') IS NULL)
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.