NULL
值的概念是造成SQL的新手的混淆的普遍原因,他们经常认为NULL
是和一个空字符串''
的一样的东西。不是这样的!例如,下列语句是完全不同的:
mysql> INSERT INTO my_table (phone) VALUES (NULL); mysql> INSERT INTO my_table (phone) VALUES ("");
两个语句把值插入到phone
列,但是第一个插入一个NULL
值而第二个插入一个空字符串。第一个的含义可以认为是“电话号码不知道”,而第二个则可意味着“她没有电话”。
在SQL中,NULL
值在于任何其他值甚至NULL
值比较时总是假的(FALSE)。包含NULL
的一个表达式总是产生一个NULL
值,除非在包含在表达式中的运算符和函数的文档中指出。在下列例子,所有的列返回NULL
:
mysql> SELECT NULL,1+NULL,CONCAT('Invisible',NULL);
如果你想要寻找值是NULL
的列,你不能使用=NULL
测试。下列语句不返回任何行,因为对任何表达式,expr = NULL
是假的:
mysql> SELECT * FROM my_table WHERE phone = NULL;
要想寻找NULL
值,你必须使用IS NULL
测试。下例显示如何找出NULL
电话号码和空的电话号码:
mysql> SELECT * FROM my_table WHERE phone IS NULL; mysql> SELECT * FROM my_table WHERE phone = "";
在MySQL中,就像很多其他的SQL服务器一样,你不能索引可以有NULL
值的列。你必须声明这样的列为NOT NULL
,而且,你不能插入NULL
到索引的列中。
当用LOAD DATA INFILE
读取数据时,空列用''
更新。如果你想要在一个列中有NULL
值,你应该在文本文件中使用\N
。字面上的词'NULL'
也可以在某些情形下使用。见7.16 LOAD DATA INFILE
句法。
当使用ORDER BY
时,首先呈现NULL
值。如果你用DESC
以降序排序,NULL
值最后显示。当使用GROUP BY
时,所有的NULL
值被认为是相等的。
为了有助于NULL
的处理,你能使用IS NULL
和IS NOT NULL
运算符和IFNULL()
函数。
对某些列类型,NULL
值被特殊地处理。如果你将NULL
插入表的第一个TIMESTAMP
列,则插入当前的日期和时间。如果你将NULL
插入一个AUTO_INCREMENT
列,则插入顺序中的下一个数字。
在《SQL-3参考大全》中,作者这样解释NULL的含义:未知或未定义。对NULL来说,有很多有趣的特性。
NULL是一个数据值,而且它属于一个域(?)。是的,例如一个字符串字段,其中的空值只能是一个字符串。尽管它的内容没有定义,或者未知,但它是字符串,这一点无可置疑。
NULL不是非法数据,这一点SQL-3 标准也说的很清楚。我们没有办法保存零分之一,但可以保存空值。虽然它是空值,是未定义,是未知,可它也的确是 一个合法的信息。
运算黑洞:对于NULL,一般的运算都会返回NULL。比如加减乘除,这简直就是一个黑洞一样。永远不会有什么数据等于NULL。当然,1不等于NULL,2也一样。可是,NULL也不等于NULL。说一个NULL等于NULL是错误的。所以我们只能比较它“是”或“不是”。为了避免混乱,SQL-3标准有一些约定。比如表达式 x=NULL,结果应当是UNKOWN 。 而表达式“x is NULL”,就得看情况,如果x是NULL或 False,就返回Ture(?);x是非NULL,返回False。有点奇怪是不是,它基于NULL不等于NULL。 这个规则的确为SQL标准所支持,遇到这样的数据库系统,可不要感到惊讶。
三值逻辑:《鹿鼎记》中的韦小宝,整人的秘诀之一就是“我问你话,是就点头,不是就摇头,不许你出声!”的确,通常我们的逻辑观点,总是基于这种二值逻辑体系,对就是对,错就是错。可在关系理论中,没有这么简单。有一种没有绝对是非的情况存在:NULL。这就是关系理论的三值逻辑。
还有一些常见的与NULL相关的情况。比如,统计函数(也有的文档称之为聚集函数、集函数)通常会忽略NULL。不过,假设有这样一个表T:
C
-----
1
2
NULL
NULL
我们分别执行两个查询:SELECT COUNT(*) FROM T和SELECT COUNT(C) FROM T, 猜猜会有什么不同?起初,我以为两个结果应当一样。结果,前一个是4,后一个是2。前一个等于4,显然基于NULL也是数据这个事实;而后一个结果为2,是由于统计C列时,COUNT忽略了NULL。
SQL-3标准中,搜索条件(WHERE和HAVING)只接受TRUE,而约束却只拒绝FALSE,二者对NULL的接受态度相反。所以我们前面见到的ROOMS表才可以把空值写入人员字段。而在排序时,却又没什么规律。SQL标准只作出了一个补充定义,所以每个DBMS的处理 ORDER BY的方法并不相同,当然NULL不是高于所有值就是低于所有值。
在《SQL-3参考大全》中介绍了更详细的关于NULL的内容。另外,书中还介绍了两位数据库专家C.J.Date和E.f.Codd关于NULL的不同论点(E.F.Codd甚至希望有四值逻辑)有兴趣的朋友可以找来一读。在实践中,我们还会遇到一些有趣的事,特别是联接查询中, NULL让我们的人生变得 “丰富多彩”。