MySQL不支持DECODE函数,需用CASE WHEN替代;分简单CASE(等值匹配)和搜索CASE(任意条件),后者更常用;注意NULL处理、类型转换、索引失效等陷阱。

MySQL里没有DECODE函数,得用CASE WHEN
Oracle用户迁移到MySQL时最容易卡在这儿:DECODE在MySQL中根本不存在。MySQL只支持标准SQL的CASE表达式,语法更严格,不能省略WHEN或ELSE(虽然ELSE可选,但漏掉常导致NULL意外返回)。它分两种写法:简单CASE value WHEN ...和搜索CASE WHEN condition THEN ...,后者更常用、更灵活。
简单CASE和搜索CASE的区别与选型
简单CASE要求所有分支都跟同一个表达式比相等,比如CASE status WHEN 'A' THEN 'Active' WHEN 'I' THEN 'Inactive';搜索CASE则支持任意布尔条件,比如CASE WHEN score >= 90 THEN 'A' WHEN score BETWEEN 80 AND 89 THEN 'B'。实际业务中多数场景需要范围判断、NULL检查或复合条件,直接上搜索CASE更稳妥。
- 简单CASE不支持
IS NULL、BETWEEN、函数调用等,一用就报错 - 搜索CASE每个
WHEN后是完整表达式,可嵌套AND/OR,也兼容子查询(但会影响性能) - MySQL 8.0+ 支持
CASE在生成列、窗口函数中使用,但5.7不支持生成列里的CASE
常见翻车点:NULL处理、类型隐式转换、性能陷阱
CASE本身不改变字段类型,但各THEN分支返回值类型不一致时,MySQL会强制转成兼容类型——比如有的返回字符串、有的返回数字,结果全变成DOUBLE或VARCHAR,可能引发后续比较异常或截断。
- 显式用
CAST(... AS CHAR)或CONVERT(..., CHAR)统一输出类型 -
WHEN条件里别直接写col = NULL,必须用col IS NULL,否则永远不匹配 - 大量
CASE分支(超过10个)且高频查询时,考虑是否该拆到应用层或建分类映射表,避免执行计划变复杂 - 在
WHERE子句里用CASE(如WHERE (CASE WHEN x=1 THEN y ELSE z END) > 10)通常无法走索引,应重写为逻辑组合
一个能直接抄的DECODE等效写法模板
假设原Oracle语句是DECODE(dept_id, 10, 'HR', 20, 'IT', 'Other'),对应MySQL写法:
CASE dept_id WHEN 10 THEN 'HR' WHEN 20 THEN 'IT' ELSE 'Other' END
如果要兼容NULL输入或带条件,改成搜索CASE更安全:
CASE WHEN dept_id = 10 THEN 'HR' WHEN dept_id = 20 THEN 'IT' WHEN dept_id IS NULL THEN 'Unknown' ELSE 'Other' END
注意:末尾没有分号,这是表达式不是语句;END不能写成END CASE(那是存储过程语法)。
真正难的不是写对语法,而是当CASE嵌套三层以上、又混着聚合和子查询时,调试起来连EXPLAIN都看不出哪段拖慢了——这时候不如先抽成视图,把逻辑切开。


















