为什么SQL不支持“= null”而不是“null”?

时间:2011-08-16 13:20:39

标签: sql null

我不是在问 。我知道事实并非如此。

我很好奇。我已经阅读了支持文档,例如on Working With Nulls in MySQL,但它们并没有给出任何理由。他们只重复你必须使用的“是空”的咒语。

这一直困扰着我。在进行动态SQL时(那些必须要做的极少数情况),将“null”传递给where子句会更容易:

@where = "where GroupId = null"

这将是常规变量的简单替换。相反,我们必须使用if / else块来执行以下操作:

if @groupId is null then
     @where = "where GroupId is null"
else
     @where = "where GroupId = @groupId"
end

在更大的更复杂的查询中,这是一个巨大的痛苦。有没有特定的原因,SQL和所有主要的RDBMS供应商都不允许这样做?它会创建某种关键字冲突或价值冲突吗?

修改

许多答案的问题(在我看来)是每个人都在设置null和“我不知道它的值是什么”之间的等价。这两件事之间存在巨大差异。如果null意味着“有一个值,但它是未知的”我会100%同意空值不能相等。但SQL null并不意味着。这意味着没有值。任何两个为null的SQL结果都没有值。 值不等于未知值。两件不同的事情。这是一个重要的区别。

编辑2:

我遇到的另一个问题是其他HLL允许null = null完全正常并适当地解决它。例如,在C#中,null = null返回true。

12 个答案:

答案 0 :(得分:21)

默认情况下关闭的原因是null在商业意义上确实不等于null。例如,如果您要加入订单和客户:

select * from orders o join customers c on c.name = o.customer_name

将未知客户的订单与名称不明的客户进行匹配是没有多大意义的。

大多数数据库允许您自定义此行为。例如,在SQL Server中:

set ansi_nulls on
if null = null  
    print 'this will not print' 
set ansi_nulls off
if null = null  
    print 'this should print'

答案 1 :(得分:9)

平等是可以绝对确定的。 null的问题在于它本身就是未知数。如果您按照真值表的三值逻辑,null与任何其他值相结合null - 未知。问SQL“我的值等于 null吗?”即使输入为空,也会每次都未知。我认为IS NULL的实施表明了这一点。

答案 2 :(得分:5)

这是一种语言语义。

Null是缺乏价值。

is null对我有意义。它说,“缺乏价值”或“未知”。就个人而言,我从未问过某人是否“等于缺乏价值”。

答案 3 :(得分:4)

我不禁觉得你对目前给出的答案仍然不满意,所以我想我会尝试另一种方法。让我们举个例子(不,我不知道为什么这个具体的例子已经出现在我的脑海中)。

我们有一个员工表,EMP

EMP
---
EMPNO           GIVENNAME
E0001           Boris
E0002           Chris
E0003           Dave
E0004           Steve
E0005           Tony

而且,无论出于何种奇怪的原因,我们都会追踪每个员工在特定日期选择穿的颜色裤子(TROUS):

TROUS
-----
EMPNO       DATE        COLOUR
E0001       20110806    Brown
E0002       20110806    Blue
E0003       20110806    Black
E0004       20110806    Brown
E0005       20110806    Black
E0001       20110807    Black
E0003       20110807    Black
E0004       20110807    Grey

我可以继续。我们写了一个查询,我们想知道每个员工的名字,以及他们在8月7日穿的是什么颜色的裤子:

SELECT e.GIVENNAME,t.COLOUR
FROM
    EMP e
        LEFT JOIN
    TROUS t
        ON
             e.EMPNO = t.EMPNO and
             t.DATE = '20110807'

我们得到结果集:

GIVENNAME       COLOUR
Chris           NULL
Steve           Grey
Dave            Black
Boris           Black
Tony            NULL

现在,这个结果集可以在视图中,或者CTE中,或者其他什么,我们可能希望继续使用SQL来询问有关这些结果的问题。这些问题可能是什么?

  1. 那天戴夫和鲍里斯穿着同色系的裤子? (是的,黑色==黑色)

  2. 戴夫和史蒂夫当天穿着同样颜色的裤子? (不,黑!=灰色)

  3. 那天鲍里斯和托尼穿着同样颜色的裤子? (未知 - 我们试图与NULL进行比较,我们遵循SQL规则)

  4. 鲍里斯和托尼当天穿着同色系的裤子? (未知 - 我们再次与NULL进行比较,我们遵循SQL规则)

  5. 那天克里斯和托尼穿着同色系的裤子? (未知)

  6. 请注意,如果您将数据库设计为永远不会使用NULL作为缺失信息的标记,那么您已经了解了强制所需结果的特定机制(例如IS NULL)。

    但是在SQL中,NULL被赋予了两个角色(至少) - 标记不适用的信息(也许我们在数据库中有完整的信息,而Chris和Tony当天没有找到工作,或者确实没有不穿裤子,并标记丢失的信息(克里斯确实在那天出现了,我们目前没有记录在数据库中的信息)

    如果您仅使用NULL作为不适用信息的标记,我假设您正在避免使用外连接等构造。


    我觉得有趣的是,你在评论中提到了NaN其他答案,却没有看到NaN和(SQL)NULL有很多共同之处。它们之间最大的区别在于NULL旨在用于整个系统,无论涉及何种数据类型。

    你最大的问题似乎是你已经确定NULL在所有编程语言中都有一个含义,你似乎觉得SQL已经打破了这个含义。实际上,不同语言中的null通常具有微妙的不同含义。在某些语言中,它是0的同义词。在其他语言中,不是,因此比较0==null将在某些语言中成功,而在其他语言中则失败。你提到过VB,但VB(假设你说的是.NET版本)没有null。它有Nothing,这又是微妙的不同(它在C#构造default(T)的大多数方面都相同)。

答案 4 :(得分:3)

概念是NULL不是公平值。它表示没有值。

因此,只有变量或列IS NULL才会被检查,但如果IS EQUAL TO NULL则不能。

打开算术比较后,您可能需要与IS GREATER THAN NULLIS LESS THAN OR EQUAL TO NULL

竞争

答案 5 :(得分:3)

NULL未知。这既不是真的也不是假的,所以当你将任何事情与未知事物进行比较时,唯一的答案就是“未知”维基百科上更好的文章http://en.wikipedia.org/wiki/Null_(SQL

答案 6 :(得分:2)

因为在ANSI SQL中,null表示“未知”,这不是值。因此,它不等于任何东西;你可以只评估价值的状态(已知或未知)。

答案 7 :(得分:2)

一个。 Null不是“缺乏价值”

湾Null不是“空”

℃。 Null不是“未设置值”

以上都是,而且都不是。

根据技术权利,NULL是“未知值”。但是,就像C / C ++中未初始化的指针一样,你并不知道你指的是什么。对于数据库,它们分配空间但不初始化该空间中的值。

因此,它是一个“空”空间,因为它没有被初始化。如果将值设置为NULL,则原始值将保留在该存储位置。如果它原来是一个空字符串(例如),它将保持原样。

这是一个“缺乏价值”的事实,它没有被设置为数据库认为有效的值。

这是一个“未设置的值”,因为如果刚刚分配了空间,那里的值从未设置过。

“未知”是我们在检查NULL时真正了解的最接近的事情。


因此,如果我们尝试比较这个“未知”值,我们将得到一个比较

a)可能有效也可能无效

b)可能有也可能没有我们期望的结果

c)可能会或可能不会使数据库崩溃。

因此,DBMS系统(很久以前)认为在NULL方面使用相等甚至没有意义。

因此,“= null”毫无意义。

答案 8 :(得分:1)

除了已经说过的所有内容之外,我想强调你在第一行写的内容是错误的。 SQL 支持“= NULL”语法,但它具有与“IS NULL”不同的语义 - 正如您链接到的那篇文档中所示。

答案 9 :(得分:1)

我同意OP

where column_name = null

语法糖
where column_name is null

但是,我确实理解为什么SQL的创建者想要区分它们。在三值逻辑中(IMO这是用词不当),谓词可以返回两个值( true false )或 unknown ,这在技术上是不仅仅是一种价值,而只是一种表达方式,我们不知道这两个价值中的哪一个是"。根据三值逻辑考虑以下谓词:

A == B

这个谓词测试A是否等于B.这是真值表的样子:

    T U F
    -----
T | T U F
U | U U U
F | F U T

如果A或B未知,谓词本身总是返回未知,无论另一个是真还是假或未知。

在SQL中,null是 unknown 的同义词。所以,SQL谓词

column_name = null

测试column_name的值是否等于其值未知的值,并且无论column_name是true还是false或者是否为其他任何内容,都返回unknown,就像上面的三值逻辑一样。 SQL DML操作仅限于对where子句中的谓词返回true的行进行操作,忽略谓词返回false或unknown的行。这就是为什么"其中column_name = null"不对任何行进行操作。

答案 10 :(得分:0)

NULL不等于NULL。它不能等于NULL。 没有意义让他们平等。

考虑它的几种方法:

  1. 想象一下一个联系人数据库,其中包含FirstNameLastNameDateOfBirthHairColor等字段。如果我查找记录WHERE DateOfBirth = HairColor,它是否应匹配任何内容?如果有人的DateOfBirth为空,而他们的HairColor也是如此,该怎么办?未知的头发颜色不等于未知的其他任何

  2. 让我们将联系人表格与购买和产品表一起加入。假设我想找到一个客户购买假发的所有情况,这个假发与自己的头发颜色相同。所以我查询WHERE contacts.HairColor = product.WigColor。我是否应该在每个客户之间获得匹配,我不知道头发的颜色和没有WigColor的产品?不,他们是另一回事。

  3. 让我们考虑NULL是 unknown 的另一个词。 ('Smith' = NULL)的结果是什么?答案是 not false ,它是未知。未知不是真的,因此表现得像假(NULL = NULL)的结果是什么?答案也是未知的,因此也是有效的错误。 (这也是为什么将字符串与NULL值连接使整个字符串变为NULL - 结果确实是 unknown 。)

答案 11 :(得分:0)

为什么不使用isnull功能?

@where = "where GroupId = "+ isnull(@groupId,"null")