mysql中''与null不等价:''表示已知为空的确定值,可用=判断、参与拼接、计入count;null表示未知或缺失,须用is null判断、运算结果为null、被count忽略;二者存储机制(数据区vs位图)、索引行为及约束处理均不同。

MySQL 中 '' 和 NULL 不等价,不是设计疏漏,而是语义分层的必然结果:一个表示“已知为空”,另一个表示“未知是否存在”。IS NULL 判断的不是值内容,而是字段的“空值标记位”状态。
为什么 '' = NULL 永远不成立
MySQL 的三值逻辑(True/False/Unknown)决定了任何与 NULL 的等值比较都返回 Unknown,而非 False。这包括 '' = NULL、0 = NULL、甚至 NULL = NULL。
-
WHERE col = NULL实际被优化为恒假,查不到任何行(哪怕该列全是NULL) -
WHERE col = ''是标准字符串比较,只匹配存储了空字符串的行 -
SELECT '' IS NULL返回0(即 false),证明二者在系统层面被明确区分
IS NULL 查的是“NULL位图”,不是数据内容
InnoDB 行格式中,NULL 值不存于数据区,而由单独的“NULL位图(NULL bitmap)”标记哪些列为 NULL。这意味着:
-
IS NULL本质是位运算:检查对应 bit 是否为 1 -
''占用实际数据空间(哪怕长度为 0),不会触发 NULL 位图置位 - 即使你把
varchar列设为NOT NULL,仍可插入'';但无法插入NULL—— 这说明约束作用对象不同
聚合函数和索引行为暴露根本差异
语义差异直接反映在执行层:
-
COUNT(col)忽略NULL,但计入'';COUNT(*)统计所有行,与两者无关 - 唯一索引允许无限个
NULL(因视为“不参与比较”),但只允许一个''(因它是确定值) - 二级索引中,
WHERE col = ''可走索引查找;WHERE col IS NULL虽也能用索引,但需额外跳过 NULL 区域,优化器更易退化为全表扫描
真正容易被忽略的点在于:应用层常把前端空输入统一转成 NULL 或 '',却不校验字段是否允许 NULL、是否有默认值、是否加了 NOT NULL 约束——这些都会让 IS NULL 的行为变得不可预测。业务语义一旦错位,修复成本远高于建表时多想一秒。











