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

soh*_*970 25 sql null

我没有问,如果它.我知道事实并非如此.

我很好奇原因.我已经阅读了支持文档,例如关于在MySQL中使用Nulls的支持文档,但它们并没有给出任何理由.他们只重复你必须使用的"是空"的口头禅.

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

@where = "where GroupId = null"
Run Code Online (Sandbox Code Playgroud)

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

if @groupId is null then
     @where = "where GroupId is null"
else
     @where = "where GroupId = @groupId"
end
Run Code Online (Sandbox Code Playgroud)

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

编辑:

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

编辑2:

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

And*_*mar 22

它默认是关闭的原因nullnull在商业意义上真的不等于它.例如,如果您要加入订单和客户:

select * from orders o join customers c on c.name = o.customer_name
Run Code Online (Sandbox Code Playgroud)

将未知客户的订单与名称未知的客户进行匹配是没有意义的.

大多数数据库允许您自定义此行为.例如,在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'
Run Code Online (Sandbox Code Playgroud)


Yuc*_*uck 9

平等是可以绝对确定的.麻烦的null是,它本身就是未知数.如果你遵循真值表的三值逻辑,null结合任何其他值是null- 未知.问SQL"我的值是否等于 null?" 即使输入为空,每次都是未知的.我认为实施表明IS NULL了这一点.

  • @ Sohtimsso1970 - "数据库*中没有数据值*" - 这并不是一个断言,该值对于被建模的项目不一定存在,只是它是"缺少信息[或]不适用的信息". (5认同)
  • @ sohtimsso1970数学是数学,Equal具有特定含义,null具有特定含义,在逻辑上不能与=一起使用.对不起,你不同意它,这对你来说似乎不方便但是哦,世界并没有按照你的需要订购. (3认同)
  • @ Sohtimsso1970 - 你将四个字母(NULL)的含义归结为没有特定的固有含义.它不再*意味着***没有价值**而不是意味着**未知**.但是,在SQL语言中,它被定义为缺少或未知信息的占位符.在询问有关SQL的问题时,它在其他语言中的意义无关紧要. (3认同)
  • "null"实际上可以表示"不适用","未知"或"价值不存在".那些不是等同的情况. (2认同)

Jus*_*ner 5

这是一种语言语义.

空缺是缺乏价值.

is null我感觉合理.它说,"缺乏价值"或"未知".我个人从来没有问过某人是否"等于缺乏价值".

  • 同意 - "= null"似乎意味着两个不存在的东西是相等的...即,`lochNessMonster = bigFoot`,只是因为它们都不存在(至少,我认为不是;-)) (3认同)

Dam*_*ver 5

我不禁感到您对到目前为止给出的答案仍然不满意,所以我想我会尝试另一种方法。让我们举一个例子(不,我不知道为什么这个特定的例子会出现在我的脑海中)。

我们为员工准备了一张桌子EMP

EMP
---
EMPNO           GIVENNAME
E0001           Boris
E0002           Chris
E0003           Dave
E0004           Steve
E0005           Tony
Run Code Online (Sandbox Code Playgroud)

而且,无论出于何种奇怪的原因,我们都在跟踪每位员工在特定日期选择穿什么颜色的裤子 ( 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
Run Code Online (Sandbox Code Playgroud)

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

SELECT e.GIVENNAME,t.COLOUR
FROM
    EMP e
        LEFT JOIN
    TROUS t
        ON
             e.EMPNO = t.EMPNO and
             t.DATE = '20110807'
Run Code Online (Sandbox Code Playgroud)

我们得到结果集:

GIVENNAME       COLOUR
Chris           NULL
Steve           Grey
Dave            Black
Boris           Black
Tony            NULL
Run Code Online (Sandbox Code Playgroud)

现在,这个结果集可能在视图、CTE 或其他任何东西中,我们可能想继续使用 SQL 询问有关这些结果的问题。其中一些问题可能是什么?

  1. 戴夫和鲍里斯那天穿的是同一种颜色的裤子吗?(是的,黑色==黑色)

  2. 戴夫和史蒂夫那天穿的是同一种颜色的裤子吗?(不,黑色!=灰色)

  3. 那天鲍里斯和托尼穿的是同一种颜色的裤子吗?(未知 - 我们正在尝试与 NULL 进行比较,并且我们遵循 SQL 规则)

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

  5. 那天克里斯和托尼穿的是同一种颜色的裤子吗?(未知)

请注意,IS NULL如果您将数据库设计为从不使用 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))。


Jer*_*acs 2

因为在ANSI SQL中,null的意思是“未知”,它不是一个值。因此,它不等于任何东西;您可以只评估值的状态(已知或未知)。

  • 这是一个 ANSI SQL 定义。在SQL Server 中,如果关闭ANSI_NULLS 选项,(NULL = NULL) 为true...否则,(NULL = NULL) 为NULL。 (2认同)