MySQL中的NULL值问题
NULL值的含义
在MySQL中,NULL
是一个特殊值,表示字段没有数据。当一列被定义为可包含NULL
时(即没有设置NOT NULL
约束),确切的存储需求取决于使用的存储引擎和行格式。
对于大多数存储引擎(例如InnoDB),NULL
值通常不会存储任何实际的数据,但每个可为NULL
的列都需要一些额外的空间来记录其NULL
状态。这通常是通过NULL位图来完成的,即在表的每一行内部都有一个位图,每个可为NULL
的列由该位图中的一个位来表示。如果列的值为NULL
,则相应的位被置为1(或者根据具体实现可能是0);如果列有值,则置为另一个值。
- InnoDB存储引擎:在InnoDB里,与
NULL
相关的开销主要是行记录中的NULL位图。例如,如果您有8个可为NULL
的列,那么至少需要1个字节来存储这些列的NULL
标志位,不管这些列是否实际包含NULL
值。 - MyISAM存储引擎:MyISAM使用不同的数据组织方式,但也同样会有用于存储
NULL
状态的位图。
NULL值的查询和比较
在SQL中,NULL值在与任何其他值进行比较时永远不会返回真值,即使是与NULL本身比较也如此。包含NULL的表达式总会得出NULL值,除非特定操作符和函数的文档中有其他说明。例如,在下面的查询中所有列都会返回NULL:
mysql> SELECT NULL, 1+NULL, CONCAT('Invisible',NULL);
搜索列值中的NULL,不能使用expr = 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 = '';
在进行数学比较时,不能使用=
, <
, 或 <>
等算术比较运算符来和NULL值比较。比较结果均是null值,例如:
mysql> SELECT 1 = NULL, 1 <> NULL, 1 < NULL, 1 > NULL;
+----------+-----------+----------+----------+
| 1 = NULL | 1 <> NULL | 1 < NULL | 1 > NULL |
+----------+-----------+----------+----------+
| NULL | NULL | NULL | NULL |
+----------+-----------+----------+----------+
在SQL中,NULL永远不会在比较中返回true,即使与NULL自身比较也不例外。所有包含NULL的表达式都将产生NULL值,除非文档中对涉及的操作符和函数有特别说明。例如,聚合函数(如COUNT()、MIN()和SUM())在计算时会忽略NULL值,只有COUNT(*)
则会统计包括那些具有NULL值的行。
插入NULL值
许多初学者常常误将NULL与空字符串''
混淆。但实际上,它们代表的含义完全不同。以下两个INSERT语句清楚地展示了这一区别:
mysql> INSERT INTO my_table (phone) VALUES (NULL);
mysql> INSERT INTO my_table (phone) VALUES ('');
第一个语句表示电话号码未知,而第二个则表示该人确实没有电话号码。
SQL中GROUP BY、ORDER BY对NULL值的处理
- 当使用
DISTINCT
、GROUP BY
或ORDER BY
时,所有NULL值被视为相等。 - 在使用
ORDER BY
时,NULL值默认会排在最前面,或者如果指定DESC
降序排序,则会排在最后。
NULL对索引的影响
-
单列索引:在单列索引中,如果该列包含多个
NULL
值,MySQL 会将这些NULL
值都视为相同,并且在索引中为它们创建一个条目。这意味着,即便表中有多行具有NULL
值,索引结构中通常只需要一个条目来表示所有的NULL
。 -
复合索引:当一个索引涵盖多个列时(即复合索引),如果其中一列为
NULL
,那么这一组合(包括NULL
)仍然会被索引。但是,由于索引条目是按列组合创建的,所以每个包含NULL
的不同组合都会被分别索引。 -
索引搜索:在执行等值查询时,你可以搜索
NULL
值,例如WHERE column IS NULL
。MySQL 会使用索引来快速找到NULL
值的位置。然而,要注意的是NULL
不等同于空字符串或零;它被认为是一个特殊的“不存在”的值。 -
排序和分组:在使用
ORDER BY
或GROUP BY
子句时,NULL
值通常会被视作低于任何其他的非空值,并且在默认情况下会出现在结果集的开始部分(当使用升序排列时)。 -
唯一索引:在具有唯一约束的索引中,
NULL
值被视作不同于彼此的,也就是说,在满足唯一性约束的前提下,你可以有多行包含NULL
值。这与某些其他数据库系统(如 SQL Server)不同,在那里唯一索引通常不允许多个NULL
值。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!