漏写else会导致null静默注入,不报错难定位;业务逻辑中几乎不可省略,应显式写else '未知'或else 0以保障数据可控性与执行计划稳定。

ELSE 子句语法上可省略,但业务逻辑中它几乎不可省略——不是数据库强制要求,而是漏写会导致 NULL 静默注入,且不报错、难定位。
SELECT 中漏 ELSE 会返回一堆看不见的 NULL
只要 WHEN 条件没覆盖全(比如字段含 NULL、空字符串、负数、边界外值),又没写 ELSE,数据库就按 SQL 标准返回 NULL。这不是错误,所以日志里不会报警,前端可能只显示空白,报表统计突然少几百分之一数据,你得翻半天才意识到是 CASE 漏兜底。
- 显式写
ELSE '未知'或ELSE 0,比依赖隐式NULL更可控 - 如果业务真需要
NULL,也请写成ELSE NULL,让意图可读 - 用
COALESCE()在外层补救是绕路,源头加ELSE才是正解
WHERE 中滥用 CASE WHEN + 缺 ELSE 可能让索引失效
CASE WHEN 放在 WHERE 里本就危险,再缺 ELSE,会让优化器更难推导谓词含义。例如 WHERE CASE WHEN status = 'A' THEN 1 END = 1,实际等价于 WHERE status = 'A' AND status IS NOT NULL,但数据库未必能识别这个等价关系,最终走全表扫描。
- 优先用原生布尔表达式替代
CASE判断,比如直接写status = 'A' - 非要用
CASE做动态过滤时,ELSE 0或ELSE FALSE比缺省更利于执行计划稳定 - MySQL 8.0+ 和 PostgreSQL 15+ 虽支持函数索引,但
CASE表达式本身不能被索引直接加速
类型不一致时,缺 ELSE 会让错误延迟暴露
当各 THEN 分支返回不同类型(比如 THEN 'active' 和 ELSE 0),PostgreSQL 会直接报错;但 MySQL 可能静默转成字符串或数字,结果不可靠。而如果你压根没写 ELSE,PostgreSQL 仍会尝试统一类型——若其他分支是字符串,隐式 ELSE NULL 会被当成 TEXT 类型;但一旦某条路径实际返回了数字,类型冲突就在运行时爆发。
- 所有
THEN和ELSE必须返回同一大类类型:全字符串、全数值、全日期 - 数值类优先统一为
DECIMAL或INTEGER,避免浮点精度问题 - 字符串类注意长度,
ELSE '超长描述'可能被截断,影响后续排序或比较
嵌套多层时,缺 ELSE 容易导致逻辑断裂
三层以上 CASE WHEN 嵌套,人眼很难快速定位哪条路径生效。如果中间某层漏了 ELSE,整条链路就提前返回 NULL,后面所有判断都跳过。比如:
SELECT CASE WHEN flag = 1 THEN
CASE WHEN score > 90 THEN 'A'
WHEN score > 60 THEN 'B'
-- 这里漏了 ELSE,score <p>这种写法看着没问题,但 <code>flag = 1 AND score 的记录会变成 <code>NULL</code>,而不是预期的 <code>'other'</code>。</code></p>
- 避免
WHEN ... THEN CASE ... END这种内联嵌套 - 主干逻辑先抽成计算列,或拆进 CTE,让每层
CASE职责单一 - 上线前必须用边界数据验证:空值、负数、刚好卡在临界点的值
最麻烦的从来不是语法写错,而是那个默默返回 NULL 的缺失 ELSE——它不报错,却可能让订单少统计、用户等级错标、报表口径漂移。写的时候顺手加上,比出问题后花三小时查数据链路强得多。










