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值的处理

  • 当使用DISTINCTGROUP BYORDER BY时,所有NULL值被视为相等。
  • 在使用ORDER BY时,NULL值默认会排在最前面,或者如果指定DESC降序排序,则会排在最后。

NULL对索引的影响

  1. 单列索引:在单列索引中,如果该列包含多个 NULL 值,MySQL 会将这些 NULL 值都视为相同,并且在索引中为它们创建一个条目。这意味着,即便表中有多行具有 NULL 值,索引结构中通常只需要一个条目来表示所有的 NULL

  2. 复合索引:当一个索引涵盖多个列时(即复合索引),如果其中一列为 NULL,那么这一组合(包括 NULL)仍然会被索引。但是,由于索引条目是按列组合创建的,所以每个包含 NULL 的不同组合都会被分别索引。

  3. 索引搜索:在执行等值查询时,你可以搜索 NULL 值,例如 WHERE column IS NULL。MySQL 会使用索引来快速找到 NULL 值的位置。然而,要注意的是 NULL 不等同于空字符串或零;它被认为是一个特殊的“不存在”的值。

  4. 排序和分组:在使用 ORDER BYGROUP BY 子句时,NULL 值通常会被视作低于任何其他的非空值,并且在默认情况下会出现在结果集的开始部分(当使用升序排列时)。

  5. 唯一索引:在具有唯一约束的索引中,NULL 值被视作不同于彼此的,也就是说,在满足唯一性约束的前提下,你可以有多行包含 NULL 值。这与某些其他数据库系统(如 SQL Server)不同,在那里唯一索引通常不允许多个 NULL 值。

你可能感兴趣的:(mysql,mysql)