SQL 中 NULL 的三值逻辑详解

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

sql 中 null 的三值逻辑详解

WHERE 条件里写 = NULL 为什么查不到数据?

因为 = NULL 永远不返回 TRUE,而是返回 UNKNOWN;而 WHERE 只保留结果为 TRUE 的行,UNKNOWNFALSE 都被过滤掉。

  • 错误写法:WHERE status = NULL → 实际等价于 WHERE UNKNOWN → 无匹配行
  • 正确写法:WHERE status IS NULLWHERE status IS NOT NULL
  • 连带陷阱:WHERE score != 80 会漏掉 scoreNULL 的所有行,因为 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 类逻辑,可先排除 NULLNOT 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,永远不命中。

WeShop唯象

WeShop唯象

WeShop唯象是国内首款AI商拍工具,专注电商产品图片的智能生成。

下载

  • 错误写法: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 → NULLTRUE OR anything → TRUE(仍短路),但 FALSE OR NULL → NULL

  • 典型陷阱:WHERE active = 'Y' AND score > 80 —— 若某行 scoreNULL,整条件为 UNKNOWN,该行被排除(即使 active = 'Y'TRUE
  • 业务含义上,这代表“我们不知道该用户分数是否达标”,所以不能算作“达标用户”——这是设计使然,不是 bug
  • 调试技巧:在复杂条件中临时拆解,用 SELECT col, col IS NULL, col = 'X', (col = 'X') IS UNKNOWN 查看各部分真值
  • 真正危险的是把 UNKNOWN 当成 FALSE 处理,比如权限校验中漏掉 IS NULL 分支,可能意外放行或拦截

三值逻辑不是数据库的缺陷,而是对“未知”这一现实状态的诚实建模。问题往往不出在 NULL 本身,而出在用二值逻辑的习惯去写三值逻辑的代码。

https://www.php.cn/faq/2026648.html

发表回复

Your email address will not be published. Required fields are marked *