数据库中CASE WHEN与IF用途严格分离:存储过程必须用IF-ELSEIF-ELSE流程控制,禁用CASE WHEN;普通查询中IF不可用,CASE仅作表达式返回标量值。

不能在存储过程中用 CASE WHEN 做流程控制,也不能在普通查询里用 IF。 这是数据库语法层级的硬性限制,不是风格偏好——混用直接报错或逻辑错乱。
MySQL 存储过程必须用 IF-ELSEIF-ELSE,不支持 CASE WHEN 流程分支
MySQL 的存储过程语法明确禁止用 CASE WHEN 替代流程控制。写 CASE WHEN @x = 1 THEN ... END 在过程体里会触发 ERROR 1064。
-
IF必须连写为ELSEIF(中间不能有空格),漏掉THEN或END IF都会解析失败 - 多层嵌套超过 4 层就该重构:用
DECLARE status_code TINYINT统一计算分支依据,再单层IF status_code = 1判断 -
@a = 'x' AND @b = 'y'中任一变量为NULL,整条条件结果为UNKNOWN,等同于FALSE,常误入ELSE分支——必须显式写成@a IS NOT NULL AND @a = 'x'
SQL Server 和 PostgreSQL 里 IF 是语句,CASE 是表达式,分工不能颠倒
IF 只能控制后续语句块是否执行,不返回值;CASE 可嵌入 SELECT、WHERE、ORDER BY,但返回的是标量值。
- 想根据参数决定查哪张表?用
IF @mode = 'daily' BEGIN SELECT ... FROM daily_log END ELSE BEGIN SELECT ... FROM hourly_log END - 想把
status字段转成中文标签?必须用CASE WHEN status = 1 THEN '待处理' ELSE '已完成' END AS status_text,不能塞进IF -
WHERE col = CASE @flag WHEN 1 THEN 'A' END会让优化器放弃使用col上的索引——应改用WHERE (@flag = 1 AND col = 'A') OR (@flag 1 AND ...)
CASE WHEN 在视图和查询中必须用搜索型语法,且 ELSE 不可省略
视图里只允许 CASE 出现在 SELECT、ORDER BY 或 HAVING 中,简单 CASE dept_no WHEN 'd001' 无法处理 NULL 或范围判断,90% 的实际需求得靠搜索型。
- 所有
THEN返回值类型必须一致:CASE WHEN flag = 1 THEN 'yes' ELSE 0 END会隐式转成字符串,但可能在排序或聚合时报错——统一写成ELSE 'no' - 没写
ELSE时默认返回NULL,若后续用于SUM(CASE WHEN paid = 1 THEN amount END),NULL会被忽略,但若用于WHERE过滤就可能漏数据 - 在
ORDER BY中用CASE控制优先级时,必须写完整表达式:ORDER BY CASE WHEN is_top = 1 THEN 0 ELSE 1 END, created_at DESC,不能简写为ORDER BY top_weight
复杂分支别堆嵌套,先抽状态码再映射,比硬写 IF 或 CASE 更可靠
当分支依据来自多表 JOIN、子查询或函数调用时,直接塞进 IF 条件或 CASE WHEN 会导致每次调用都重复执行——尤其 WHEN (SELECT COUNT(*) FROM huge_log WHERE ...) 这种低命中率判断,99.9% 的请求都在白跑。
- 把分支依据提前算好:用
SELECT @status_code = COALESCE((SELECT type_code FROM config WHERE key = @input), 0)赋值 - 用
IF @status_code IN (1,2,3)做主路由,再用CASE处理具体字段转换,避免逻辑耦合 - 高频分支(比如
@status = 'published'占 95%)必须前置,数据库严格按书写顺序求值,不会自动优化顺序
真正容易被忽略的是:IF 的作用域仅限于过程体,CASE 的生命只在当前查询行。跨这两层混用,不是性能问题,是语法死区。

















