= NULL 查不到数据,因为其结果为 UNKNOWN 而非 TRUE,WHERE 只保留 TRUE 行;应使用 IS NULL。NOT IN 遇 NULL 恒为 UNKNOWN,推荐改用 NOT EXISTS 或排除 NULL。

WHERE 条件里写 = NULL 为什么查不到数据?
因为 = NULL 永远不返回 TRUE,而是返回 UNKNOWN;而 WHERE 只保留结果为 TRUE 的行,UNKNOWN 和 FALSE 都被过滤掉。
- 错误写法:
WHERE status = NULL→ 实际等价于WHERE UNKNOWN→ 无匹配行 - 正确写法:
WHERE status IS NULL或WHERE status IS NOT NULL - 连带陷阱:
WHERE score != 80会漏掉score为NULL的所有行,因为NULL != 80也是UNKNOWN - 安全补救:
WHERE score != 80 OR score IS NULL或用COALESCE(score, -1) != 80
NOT IN 子查询一遇到 NULL 就失效?
是的。只要子查询结果中包含任意一个 NULL,整个 NOT IN 表达式就恒为 UNKNOWN,导致主查询返回空集——没有报错,也没有提示,非常隐蔽。
- 根本原因:
id NOT IN (1, 2, NULL)等价于id != 1 AND id != 2 AND id != NULL,最后一项为UNKNOWN,整条逻辑变为UNKNOWN - 替代方案:改用
NOT EXISTS(它只返回TRUE/FALSE,不引入UNKNOWN) - 示例:
WHERE NOT EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.id) - 若必须用
IN类逻辑,可先排除NULL:NOT IN (SELECT customer_id FROM orders WHERE customer_id IS NOT NULL)
CASE WHEN 里怎么安全判断 NULL?
CASE 的简单形式(CASE col WHEN value THEN ...)底层会做等值比较,所以 WHEN NULL 实际执行的是 col = NULL → 恒为 UNKNOWN,永远不命中。
- 错误写法:
CASE col WHEN NULL THEN 'missing' ELSE 'ok' END→'missing'永远不会出现 - 正确写法(搜索型
CASE):CASE WHEN col IS NULL THEN 'missing' ELSE 'ok' END - 聚合场景常见坑:
COUNT(col)忽略NULL,但COUNT(*)统计所有行;别误以为两者等价 - JOIN 后字段可能为
NULL,例如LEFT JOIN右表无匹配时,直接参与计算(如score * 1.1)会得NULL,建议用COALESCE(score, 0)防御
三值逻辑下 AND/OR 的“短路”行为和直觉相反?
不是完全不短路,而是规则变了:FALSE AND anything → FALSE(仍短路),但 TRUE AND NULL → NULL;TRUE OR anything → TRUE(仍短路),但 FALSE OR NULL → NULL。
- 典型陷阱:
WHERE active = 'Y' AND score > 80—— 若某行score为NULL,整条件为UNKNOWN,该行被排除(即使active = 'Y'为TRUE) - 业务含义上,这代表“我们不知道该用户分数是否达标”,所以不能算作“达标用户”——这是设计使然,不是 bug
- 调试技巧:在复杂条件中临时拆解,用
SELECT col, col IS NULL, col = 'X', (col = 'X') IS UNKNOWN查看各部分真值 - 真正危险的是把
UNKNOWN当成FALSE处理,比如权限校验中漏掉IS NULL分支,可能意外放行或拦截
三值逻辑不是数据库的缺陷,而是对“未知”这一现实状态的诚实建模。问题往往不出在 NULL 本身,而出在用二值逻辑的习惯去写三值逻辑的代码。










