【发布时间】:2011-02-14 11:55:32
【问题描述】:
“=null”和“IS NULL”有什么区别?它们的使用方式有何不同?
【问题讨论】:
“=null”和“IS NULL”有什么区别?它们的使用方式有何不同?
【问题讨论】:
在WHERE子句中,column=null永远不会为真,这样使用null是无效的,你需要说column IS NULL或column IS NOT NULL。这说明了NULL 的特殊性,它不是检查是否相等的值,它是一个未知值,因此您需要使用IS 或IS NOT 语法。
您可以使用 = 相等来分配 NULL 值。例如:UPDATE TableX SET Column=NULL...
链接:
Wikipedia NUll (SQL)
w3schools SQL NULL Values
SQL Tutorial, see IS NULL Operator section
【讨论】:
可以在以下链接中找到关于同一问题的更详细讨论
http://www.sqlservercentral.com/articles/T-SQL/understandingthedifferencebetweenisnull/871/
不确定是否可以在不登录网站的情况下阅读这篇文章,因此在此处发布这篇文章的摘录。
当一个变量在 SQL 中使用 declare 语句创建时,它是在没有数据的情况下创建的,并存储在 SQL 内存空间内的变量表 (vtable) 中。 vtable 包含变量的名称和内存地址。但是,在创建变量时,没有为变量分配内存地址,因此变量不是根据内存定义的。
当您设置变量时,它被分配一个内存地址,初始数据存储在该地址中。当您再次设置该值时,该变量指向的内存地址中的数据将更改为新值。
现在了解差异以及为什么每个人的行为方式都如此。
= NULL 是值的表达式。这意味着,如果已设置变量并创建用于存储数据的内存,则它具有值。变量实际上可以设置为 NULL,这意味着对象的数据值是未知的。如果该值已设置为:
DECLARE @val CHAR(4)
SET @val = NULL
您已将数据的值明确设置为未知,因此当您这样做时:
If @val = NULL
它将评估为一个真实的表达式。
但如果我这样做:
DECLARE @val CHAR(4)
If @val = NULL
它将评估为假。
原因是我正在检查 NULL 作为@val 的值。由于我没有设置@val 的值,因此没有分配内存地址,因此@val 不存在任何值。
注意:请参阅关于 SET ANSI_NULLS (ON|OFF) 的部分,因为 SQL 7 和 2000 默认值存在差异,导致示例无法工作。这是基于 SQL 7 的。
现在IS NULL 有点棘手,它是评估变量为 NULL 的条件的首选方法。当您使用“IS NULL”子句时,它会检查变量的地址和变量中的数据是否未知。因此,例如,如果我这样做:
DECLARE @val CHAR(4)
If @val IS NULL
PRINT ‘TRUE’
ELSE
PRINT ‘FALSE’
SET @val = NULL
If @val IS NULL
PRINT ‘TRUE’
ELSE
PRINT ‘FALSE’
两个输出都是TRUE。原因是在第一个@val IS NULL 我只声明了变量,并且没有为“IS NULL”检查的数据设置地址空间。在第二个中,该值已显式设置为 NULL,“IS NULL”也会检查。
设置 ANSI_NULLS (ON|OFF)
现在让我来解决一下问题。在前面的示例中,您看到 = NULL 只要明确设置了值就会起作用。但是,当您 SET ANSI_NULLS ON 时,情况会有所不同。
例如
DECLARE @val CHAR(4)
SET @val = NULL
SET ANSI_NULLS ON
If @val =NULL
PRINT ‘TRUE’
ELSE
PRINT ‘FALSE’
SET ANSI_NULLS OFF
If @val =NULL
PRINT ‘TRUE’
ELSE
PRINT ‘FALSE’
您会注意到,在执行 SET ANSI_NULLS ON 后第一次运行 = NULL 语句时,您会得到 FALSE,而在设置 OFF 后,您会得到 TRUE。原因如下。
摘自 SQL BOL 文章“SET ANSI_NULLS”
SQL-92 标准要求针对空值的等于 (=) 或不等于 () 比较的计算结果为 FALSE。当 SET ANSI_NULLS 为 ON 时,即使 column_name 中有空值,使用 WHERE column_name = NULL 的 SELECT 语句也会返回零行。即使 column_name 中有非空值,使用 WHERE column_name NULL 的 SELECT 语句也会返回零行。
当 SET ANSI_NULLS 为 OFF 时,等于 (=) 和不等于 () 比较运算符不遵循 SQL-92 标准。使用 WHERE column_name = NULL 的 SELECT 语句返回 column_name 中具有空值的行。使用 WHERE column_name NULL 的 SELECT 语句返回列中具有非空值的行。此外,使用 WHERE column_name XYZ_value 的 SELECT 语句会返回所有非 XYZ 值且非 NULL 的行。
摘录结束
因此按照 SQL92 的定义,“= NULL”应始终评估为 false。因此,即使明确设置值也意味着您永远不会满足 = NULL if 条件,并且您的代码可能无法按预期工作。 where = NULL 会让你大吃一惊的最大原因是,SQL 7 在出厂和安装时默认为 ANSI_NULL OFF,但 SQL 2000 默认为 ANSI_NULL ON。当然,您可以通过多种方式更改此设置,但如果您将数据库从 7 升级到 2000 并发现 = NULL 仅当您在推出默认 2000 服务器时明确设置 if 时才有效,您的代码现在会中断并可能导致数据问题。
使用 IS NULL 的另一个原因是,根据 SQL 92 指南,它仍将评估为 TRUE,因此您的代码对于升级服务器更安全。
如果总结,除非您需要检查变量的值是否设置为等于 NULL,并且您已将 ANSI_NULLS 设置为 ON,否则请始终使用“IS NULL”子句来验证变量是否为 NULL。如果使用 = NULL 代替,您可能会在尝试解决现在或将来可能出现的问题时非常头疼。
基础
提供的一些信息来自 C++ 的工作原理以及 SQL 在每种情况下的行为方式。不幸的是,据我所知,SQL 没有addressof 函数来允许我输出实际内存地址以显示幕后发生的事情。在 C++ 中,当创建变量时,变量的地址为0xddddddd(在调试中,但它也可以是不同的非真实地址)。当您第一次设置变量时,检查地址将为您提供存储数据的有效内存地址。此外,更多信息可以从 SQL Books Online 中的 IS NULL 和 SET ANSI_NULLS...部分获得。
【讨论】:
= NULL 用于赋值为 NULL 值,而IS NULL 用于确定变量是否为 NULL 值。
sssignment 为 NULL 的示例:
Update TableName Set ColumnName = NULL
在条件子句 (link) 中与 NULL 值进行比较的示例:
Select * From TableName Where ColumnName is NULL
ColumnName IS NOT Null 也可用于确保值不为 NULL。
【讨论】: