必须用搜索CASE,因其支持>、IS NULL、函数等复杂条件,而简单CASE仅限等值匹配;分支需按精确到宽泛顺序排列;务必显式写ELSE并保证各分支返回值类型一致。

多个业务分支必须用搜索 CASE,不能用简单 CASE
简单 CASE(CASE status WHEN 'A' THEN ...)只支持字段值的等值匹配,无法写 >=、IS NULL、函数或组合条件。一旦分支逻辑涉及“金额 ≥ 5000”“状态为 pending 且创建时间超 3 天”“分类码以 'X' 开头”,就必须改用搜索 CASE(CASE WHEN condition THEN ...)。
常见错误是强行在简单 CASE 里塞表达式,比如:CASE score WHEN score >= 90 THEN 'A'——这会直接报语法错误。MySQL 和 PostgreSQL 都不接受。
- 所有含比较运算符(
>、BETWEEN)、空值判断(IS NULL)、字符串处理(LEFT(code,1))的场景,一律用搜索 CASE - 简单 CASE 仅保留给纯枚举映射:如
CASE type WHEN 1 THEN '订单' WHEN 2 THEN '退款' - 混合使用时,别把两种写法混在同一 CASE 表达式里——语法不合法
CASE WHEN 分支顺序错位会导致逻辑被跳过
数据库按 WHEN 从上到下逐条判断,命中第一个 TRUE 就返回对应 THEN 结果,后续分支彻底忽略。很多人把宽泛条件放前面,导致精确分支永远不执行。
例如:CASE WHEN amount > 0 THEN '有效订单' WHEN amount >= 5000 THEN 'VIP 订单' ELSE '无效'——只要 amount 是正数,就永远进不了 VIP 分支。
- 把范围更小、条件更严格的分支往前放:先
>= 5000,再>= 1000,最后> 0 - 用
IS NULL或NOT IN这类易漏条件,务必放在靠后位置,避免被前置分支意外覆盖 - 测试时用边界值验证:传入 5000、999、0、NULL,确认每种都落到预期分支
ELSE 不写或写错类型,会让下游系统崩溃
没写 ELSE 时,所有未匹配分支都会返回 NULL。这在报表导出、BI 工具或前端渲染中常表现为字段空白,比显示“未知”更难定位问题。更隐蔽的是类型不一致:比如多数分支返回字符串,ELSE 返回数字 0,MySQL 可能隐式转成字符串 '0',但 PostgreSQL 会直接报错 ERROR: CASE types text and integer cannot be matched。
- 只要分支逻辑不能穷尽所有可能取值(包括
NULL、空字符串、异常编码),就必须显式写ELSE -
ELSE后优先用业务可读的兜底值,如ELSE '其他'、ELSE -1,而不是裸写NULL或留空 - 所有
THEN和ELSE返回值类型要一致;不确定时统一转成字符串(用CAST(... AS CHAR))或提前用COALESCE处理输入
分支太多时,别硬堆 CASE,考虑函数或映射表
超过 10–15 个分支的 CASE 表达式,SQL 可读性骤降,MySQL 解析变慢,PostgreSQL 可能编译卡顿,SQL Server 在分支超百时甚至拒绝生成执行计划。而且这类长 CASE 很难复用和测试。
- 有规律的区间判断(如金额分档、年龄分段),改用
ELT(FLOOR((amount-1)/1000)+1, '0-999', '1000-1999', ...)或自定义函数封装 - 离散值映射(如城市编码 → 城市名),建一张
code_map表,用JOIN替代几十行 WHEN - 分支逻辑来自配置或用户输入?必须走应用层拼 SQL,并对输入做白名单校验,严禁直插变量——否则就是 SQL 注入口

















