必须用IS NULL判断NULL,因NULL是缺失标记而非值,=NULL恒返回UNKNOWN被WHERE过滤;正确写法仅WHERE col IS NULL或IS NOT NULL,且需注意NULL与''的区别及括号优先级。

IS NULL 不能用等号判断,必须用专门操作符
SQL 中 NULL 不是值,而是“缺失值”的标记,所以 = NULL 或 != NULL 永远返回 UNKNOWN,实际筛选结果为空。哪怕字段确实没值,WHERE col = NULL 也查不到任何记录。
正确写法只能是 WHERE col IS NULL。这是 SQL 标准语法,所有主流数据库(MySQL、PostgreSQL、SQL Server、Oracle)都支持。
-
WHERE col = NULL→ 错误,逻辑恒假,无结果 -
WHERE col IS NULL→ 正确,匹配该字段未赋值或显式设为NULL的行 -
WHERE col IS NOT NULL→ 对应非空筛选,注意不是!= NULL
区分 NULL 和空字符串 '' 是常见误区
尤其在字符串字段(如 name、email)中,''(长度为 0 的字符串)和 NULL 是完全不同的两个状态:前者是“有值,但值为空串”,后者是“无值”。用 IS NULL 筛不出 '',反之亦然。
若需同时捕获两者,得显式合并条件:
WHERE name IS NULL OR name = ''
注意:COALESCE(name, '') = '' 在部分场景下可简化,但会隐式转换、影响索引使用,不推荐用于高频查询。
- 数值型字段不会出现
'',但可能存0,别误把0当NULL - 日期字段(如
updated_at)的NULL通常表示“从未更新”,而'1970-01-01'是具体值,不可混用
索引对 IS NULL 查询的支持因引擎而异
是否走索引取决于字段是否有索引、数据库类型及查询写法。例如:
- MySQL InnoDB:单列索引默认包含
NULL,WHERE status IS NULL可走索引(前提是status有索引) - PostgreSQL:B-tree 索引默认不存储全
NULL值,需建部分索引:CREATE INDEX idx ON t (col) WHERE col IS NULL - 带函数的写法(如
WHERE COALESCE(col, 'x') = 'x')基本无法利用原字段索引
执行前建议用 EXPLAIN 看实际执行计划,别凭经验假设。
联合条件中 IS NULL 的优先级容易被忽略
当 IS NULL 和其他条件混用时,要注意逻辑运算符优先级。SQL 中 AND 优先级高于 OR,没加括号可能导致语义偏差。
比如想查 “用户已注销(deleted_at IS NULL)且邮箱为空或未填(email IS NULL OR email = '')”,错误写法:
WHERE deleted_at IS NULL OR email IS NULL OR email = ''
这实际查的是 “已注销” 或 “邮箱为空”,而不是“已注销且邮箱为空”。正确写法必须加括号:
WHERE deleted_at IS NULL AND (email IS NULL OR email = '')
复杂条件建议始终用括号明确分组,避免调试时反复怀疑数据本身有问题。
真正麻烦的是嵌套在视图、子查询或 ORM 构建的动态 SQL 里 —— 那些地方括号容易被生成器吞掉,出问题时先检查生成的原始 SQL 里有没有漏括号。

















