case when是mysql中用于字段值动态转换的表达式,需用end闭合,分简单形式和搜索形式,后者更灵活;必须注意类型一致、条件顺序、嵌套括号及执行效率。

CASE WHEN 在 SELECT 中做字段值转换最常用
直接在查询结果里根据字段值动态生成新内容,比如把数字状态码转成中文描述。MySQL 的 CASE WHEN 不是函数而是表达式,必须搭配 END 闭合,且每个分支返回的数据类型最好一致,否则可能触发隐式转换或截断。
常见写法有两种:CASE value WHEN compare_value THEN result(简单形式),和 CASE WHEN condition THEN result(搜索形式)。后者更灵活,支持任意布尔表达式:
SELECT name,
CASE WHEN score >= 90 THEN 'A'
WHEN score >= 80 THEN 'B'
WHEN score >= 60 THEN 'C'
ELSE 'F' END AS grade
FROM students;
- 注意
ELSE虽可省略,但没匹配时会返回NULL,线上查询容易埋坑 - 条件顺序很重要:MySQL 自上而下匹配,第一个为
TRUE的分支即生效,不会继续判断 - 所有
THEN后的值应尽量同类型;混用字符串和数字(如THEN 1和THEN 'unknown')会导致整列转为字符串,数值计算失效
WHERE 子句里不能直接写 CASE WHEN 表达式作条件
很多人想这么写:WHERE CASE WHEN status = 1 THEN id > 100 ELSE id —— 这是语法错误。MySQL 不允许在 <code>WHERE 中用 CASE WHEN 返回布尔逻辑来控制行过滤。
正确做法是把逻辑拆成标准布尔表达式:
WHERE (status = 1 AND id > 100) OR (status != 1 AND id < 10)
- 如果分支多、逻辑复杂,建议先在
SELECT中用CASE算出中间标记列,再用子查询或 CTE 过滤 - 部分人误用
HAVING替代,但HAVING只适用于聚合后筛选,且性能通常更差 - 极少数场景可用
ELT()或IF()替代简单二选一,但可读性和维护性不如明确的布尔组合
UPDATE 语句中用 CASE WHEN 批量更新不同值
这是 CASE WHEN 最能体现价值的地方:一条语句更新多组不同条件下的字段值,避免多次执行 UPDATE 或应用层循环。
UPDATE orders
SET status = CASE WHEN pay_time IS NOT NULL THEN 2
WHEN created_at < DATE_SUB(NOW(), INTERVAL 30 DAY) THEN -1
ELSE 1 END
WHERE id IN (1001, 1002, 1003);
-
SET后面可以跟多个字段,每个字段都可独立使用CASE WHEN,互不影响 - 务必加
WHERE限定范围,否则全表扫描+全表更新,锁表风险极高 - 注意
CASE表达式在 UPDATE 中仍遵循“只取第一个匹配分支”,所以条件排列要审慎,尤其涉及NULL判断时(col = NULL永远为FALSE,得用IS NULL)
嵌套 CASE WHEN 容易忽略括号与优先级
当需要多层判断(比如先分大类、再分小类),有人会写成 CASE WHEN a=1 THEN CASE WHEN b>10 THEN 'X' ELSE 'Y' END ELSE ...。这种写法合法,但可读性差,出错后难定位。
更稳妥的方式是外层 CASE 每个 THEN 都包裹完整逻辑,并显式加括号提升可读性:
SELECT id,
(CASE WHEN category = 'tech'
THEN (CASE WHEN price > 500 THEN 'high' ELSE 'mid' END)
WHEN category = 'book'
THEN (CASE WHEN pages > 300 THEN 'thick' ELSE 'thin' END)
ELSE 'other' END) AS tag
FROM products;
- MySQL 不强制要求括号,但嵌套时漏括号会导致
END匹配错位,报错You have an error in your SQL syntax - 如果某分支需返回空字符串或
NULL,别写成THEN ''就完事,确认该字段是否允许为空、是否有默认值干扰 - 超三层嵌套建议拆到应用层处理,SQL 复杂度上去后,索引失效、执行计划变差的概率明显上升
CASE 是表达式不是语句——它不能单独执行,也不能出现在某些上下文(如索引定义、视图的 WHERE 推导中)。写完记得用 EXPLAIN 看执行计划,尤其当 CASE 里用了函数或子查询时。










