WHERE col = NULL 查不到数据,因为NULL表示未知,=是值比较运算符,col = NULL恒返回UNKNOWN,而WHERE只保留TRUE行;正确写法是WHERE col IS NULL。

因为NULL不是值,而是“未知”的标记,= NULL永远返回UNKNOWN,而WHERE只保留TRUE行。
WHERE col = NULL 为什么查不到数据
SQL 使用三值逻辑(TRUE/FALSE/UNKNOWN),=是值比较运算符,但NULL不代表任何具体值——它表示“缺失”或“未知”。所以email = NULL不等于“email是空的”,而是“无法判断email是否等于某个未知的东西”,结果恒为UNKNOWN。WHERE子句会丢弃所有UNKNOWN和FALSE行,只留TRUE。
常见错误现象:
-
SELECT * FROM users WHERE email = NULL返回空结果集,哪怕email列全为NULL -
WHERE age != NULL、WHERE name ''(当name为NULL时)同样无效 -
WHERE status = 'NULL'是在匹配字符串'NULL',不是判空
IS NULL 是唯一标准写法,不是语法糖
IS NULL是 SQL 标准定义的谓词(predicate),语义明确:它不参与值比较,只做存在性判断。它跨数据库兼容(MySQL、PostgreSQL、SQL Server、Oracle 全部支持),且不触发隐式类型转换。
实操要点:
- 查缺失值:
WHERE shipped_at IS NULL - 查非空值:
WHERE backup_name IS NOT NULL—— 注意这不等价于!= ''或> 0,因为空字符串和数字零都不是NULL - 建表时若写了
NOT NULL DEFAULT '',那该列根本存不了NULL,IS NULL永远查不到数据
IS NULL 能不能走索引?看引擎,别默认能或不能
索引行为取决于数据库实现和索引类型,不能一概而论:
- PostgreSQL 的 B-tree 索引默认包含
NULL,IS NULL通常能高效走索引 - MySQL InnoDB 的 B+Tree 索引默认存储
NULL,但若在联合索引中IS NULL字段不是最左前缀,或前面有范围查询(如WHERE a > 10 AND b IS NULL),可能无法利用b部分 - 执行前务必用
EXPLAIN确认:看是否有Index Scan或Index Only Scan;没有就考虑加覆盖索引或改写查询
NULL 陷阱不止在 WHERE,聚合和连接里更隐蔽
就算你记住了IS NULL,其他地方照样容易翻车:
-
COUNT(col)自动跳过NULL行,COUNT(*)统计所有行 —— 两者完全不等价 -
WHERE a.id = b.a_id AND b.status IS NULL在LEFT JOIN中,可能意外过滤掉b全为NULL的关联行,因为a.id = b.a_id在b.a_id为NULL时结果是UNKNOWN -
COALESCE(int_col, 'N/A')在 PostgreSQL 这类强类型库中会报错,必须写成COALESCE(int_col, 0)或COALESCE(int_col::text, 'N/A')
真正麻烦的不是记不住IS NULL,而是查不出数据时,第一反应是“数据有问题”,却忘了先跑SHOW COLUMNS或\d table_name确认字段是否真允许NULL、有没有默认约束。










