必须用is null或is not null判断null,因null是缺失标记而非值,=null恒返回unknown,where只保留true行;coalesce比方言函数更兼容,索引对is null支持因数据库而异。

NULL在SQL中不是值,而是“缺失”状态
直接用 = NULL 或 != NULL 永远返回 false(或 unknown),因为 NULL 不参与常规比较运算。这是初学者最常踩的坑:写 WHERE status = NULL 查不到任何数据,哪怕字段全是 NULL。
原因在于 SQL 的三值逻辑(true / false / unknown)——任何与 NULL 的等值比较结果都是 unknown,而 WHERE 只保留 true 的行。
正确做法只有两个:IS NULL 和 IS NOT NULL。它们是专门为此设计的谓词,不是函数,也不支持括号。
IS NULL 和 IS NOT NULL 的实际写法与常见误用
语法很简单,但容易手滑写错:
- ✅ 正确:
WHERE updated_at IS NULL、WHERE name IS NOT NULL - ❌ 错误:
WHERE updated_at = IS NULL(多写了=) - ❌ 错误:
WHERE IS NULL(updated_at)(误当成函数调用) - ❌ 错误:
WHERE updated_at IN (NULL)(IN对 NULL 无效,整条条件判为 unknown)
注意:部分数据库(如 PostgreSQL)支持 IS DISTINCT FROM 来安全比较含 NULL 的字段,但标准 SQL 和 MySQL/SQL Server 不支持,别依赖。
处理 NULL 的常用手段:COALESCE、CASE、NULLIF
当需要把 NULL 转成默认值(比如 0、空字符串、'N/A'),别用 IFNULL() 或 ISNULL() 这类方言函数,优先用标准的 COALESCE():
SELECT COALESCE(price, 0) AS price_display FROM products;
COALESCE() 返回第一个非 NULL 的表达式,兼容性最好(MySQL、PostgreSQL、SQL Server、Oracle 都支持)。它比嵌套 CASE WHEN x IS NULL THEN ... ELSE ... END 更简洁,也比数据库特有函数更可移植。
其他场景:
- 想把某值转成 NULL?用
NULLIF(value, 'N/A')—— 当前后相等时返回 NULL,否则返回第一个值 - 需要复杂逻辑分支?必须用
CASE WHEN col IS NULL THEN ... ELSE ... END,不能省略IS NULL - 聚合函数(
SUM、AVG等)自动忽略 NULL,通常无需额外处理,但要注意 COUNT(*) 和 COUNT(col) 的区别
索引对 IS NULL 查询的影响不可忽视
很多开发者以为加了索引就万事大吉,但 WHERE status IS NULL 在多数数据库里无法高效利用普通 B-tree 索引——因为传统索引不存储全 NULL 的键(MySQL 5.6+、PostgreSQL 除外,它们可以;SQL Server 默认不存)。
如果经常查 NULL 值,得针对性优化:
- MySQL:考虑生成列 + 索引,例如
ALTER TABLE t ADD status_is_null TINYINT GENERATED ALWAYS AS (status IS NULL) STORED,再给该列建索引 - PostgreSQL:直接在表达式上建索引,如
CREATE INDEX idx_status_null ON t ((status IS NULL)) - 通用技巧:用
status IS NULL OR status = 'active'这类组合条件时,复合索引顺序很重要,NULL 判断最好放后面
线上慢查询里,IS NULL 条件跑不出索引是最隐蔽的性能黑洞之一——看起来语句简单,执行计划却走全表扫描。











