NULL是缺失值标记,触发三值逻辑,WHERE中须用IS NULL而非= NULL;聚合函数忽略NULL(COUNT(*)除外);JOIN后NULL需显式处理。

SQL中的NULL不是值,而是一种“缺失值”的标记,它让比较和逻辑运算不再遵循常规的真假二值逻辑,而是进入三值逻辑(True/False/Unknown)体系。这意味着很多看似直观的判断会返回Unknown,进而影响WHERE筛选、JOIN条件、聚合函数结果甚至索引行为。
WHERE子句中NULL无法用=或!=判断
因为NULL参与任何等值或不等值比较(如 = NULL、!= NULL、 NULL)的结果都是Unknown,而WHERE只保留True行,所以这些表达式永远过滤不出NULL数据。
- ✅ 正确写法:WHERE col IS NULL 或 WHERE col IS NOT NULL
- ❌ 错误写法:WHERE col = NULL(恒为Unknown,等价于无匹配)
- ⚠️ 注意:WHERE col != 'A' 会漏掉col为NULL的行,因为NULL != 'A' 是Unknown,不被选中
三值逻辑下AND/OR/NOT的计算规则
SQL逻辑运算符在遇到Unknown时有明确定义:
- AND:True AND Unknown → Unknown;False AND Unknown → False(短路生效)
- OR:True OR Unknown → True(短路生效);False OR Unknown → Unknown
- NOT:NOT Unknown → Unknown
- 例如:WHERE status = 'active' AND score > 80,若score为NULL,则整条条件为Unknown,该行被排除
聚合与分组中NULL的隐式处理
大多数聚合函数(如SUM、AVG、MAX、MIN、COUNT(col))自动忽略NULL值,但COUNT(*)除外:
- COUNT(*) 统计所有行(含NULL所在行)
- COUNT(col) 只统计col非NULL的行数
- GROUP BY col 会把所有col为NULL的记录归入同一组(标准SQL行为,多数数据库支持)
- ORDER BY col 中NULL默认排在最前(ASC)或最后(DESC),具体取决于数据库实现,可显式用 NULLS FIRST / NULLS LAST 控制
JOIN和外连接中的NULL传播风险
LEFT JOIN右侧无匹配时,右表字段全为NULL;这些NULL会继续参与后续计算或过滤,容易引发意外结果:
- 若在ON条件中写 ON a.id = b.a_id AND b.status != 'inactive',当b行不存在(即b.status为NULL)时,整个ON表达式为Unknown,但LEFT JOIN仍保留左表行——此时b列全为NULL,可能误导业务逻辑
- 建议:对JOIN后可能为NULL的字段做显式检查,如 WHERE b.status IS NULL OR b.status != 'inactive',而非依赖隐式行为
- COALESCE或CASE常用于防御性处理,例如:COALESCE(b.score, 0) 避免NULL干扰数值计算










