if是mysql特有三元函数,仅支持二选一;case是标准sql语法,支持多分支、任意条件表达式,可嵌入where/group by/update等子句,且具备短路执行与类型可控优势。

IF 是 MySQL 特有、仅支持二选一的轻量函数;CASE 是标准 SQL 语法,支持多分支、任意条件表达式,且可嵌入 WHERE/GROUP BY/UPDATE 等几乎所有子句中。
IF 函数只适合单层布尔判断
它本质就是三元运算符:IF(condition, true_value, false_value)。condition 必须返回 TRUE/FALSE,不能是 NULL(score = NULL 永远不成立,得用 score IS NULL)。
- 三个参数都会被求值——哪怕 condition 为 FALSE,
false_value里的NOW()或子查询仍会执行,可能拖慢查询 - 嵌套写法难读易错:比如分三档成绩,
IF(score > 85, 'A', IF(score > 60, 'B', 'C'))容易漏边界或写反方向 - 无法处理
IN、BETWEEN、函数调用等复杂条件,也不支持IS NULL以外的 NULL 判断
CASE WHEN(搜索形式)才是主力
真正干活用的是搜索型 CASE WHEN ... THEN ... END,不是简单 CASE column WHEN value THEN ... 形式。
- 条件按顺序从上到下匹配,第一个为 TRUE 就返回对应结果,后续不再计算——所以区间判断必须倒序写:
CASE WHEN score > 85 THEN '优秀' WHEN score > 60 THEN '及格' ELSE '不及格' END - 每个
WHEN后是独立布尔表达式,可自由组合:status IN ('cancelled', 'refunded')、created_at IS NOT NULL、amount * tax_rate > 1000 - 没写
ELSE时默认返回NULL——聚合统计时可能丢行,线上 SQL 必须显式补ELSE 'unknown'
字段类型对齐容易出错
CASE 表达式的最终类型由所有 THEN 和 ELSE 分支共同决定,MySQL 会做隐式转换,但可能失控:
- 分支返回
VARCHAR(10)、INT、NULL,最终类型可能是DOUBLE或被截断的字符串 - 插入表时若目标字段是
ENUM或严格CHAR(2),隐式转换失败直接报错Truncated incorrect DOUBLE value - 安全做法:所有分支统一转成同类型,比如都用
CAST(... AS CHAR)或提前在THEN里写死长度
别在不该用的地方硬套 IF
应用层传参控制逻辑时,有人习惯把 IF(@role = 'admin', '2020-01-01', '2025-01-01') 塞进 WHERE created_at >= ...——这看着省事,但会导致 MySQL 无法使用索引,全表扫描。
- 这类动态条件更适合用应用层拼 SQL,或改用
CASE+ 覆盖索引字段(如WHERE ( @role = 'admin' AND created_at >= '2020-01-01' ) OR ( @role != 'admin' AND created_at >= '2025-01-01' )) -
IF在SELECT中做展示映射没问题,但一旦涉及过滤、分组、排序,优先考虑CASE或重构逻辑
真正麻烦的不是语法本身,而是类型推导和短路行为——前者藏在执行计划里难察觉,后者依赖你手动控制条件顺序。写完 CASE 多看一眼 EXPLAIN,再查查字段实际存进去是什么类型,比背熟语法重要得多。











