CASE在MySQL中分流程控制语句(需END CASE,可执行多条语句)和表达式(需END,返回单值),二者语法、用途严格区分,不可混用。

CASE 表达式在存储过程中不能直接当控制流语句用(比如代替 IF),但可以安全用于赋值、计算、返回值生成等表达式上下文。
存储过程里 CASE 只能用在表达式位置,不能替代 IF
很多人写 CASE ... END CASE 时以为它像编程语言的 switch 一样能控制执行分支——错了。MySQL 存储过程中的 CASE 是**流程控制语句**,语法必须是 CASE ... WHEN ... THEN ... ELSE ... END CASE(注意末尾有 CASE),且只能出现在 BEGIN...END 块内;而 SELECT 或 SET 中的 CASE WHEN ... END 是**表达式**,返回一个值,两者语法和用途完全不同。
- 流程控制语句
CASE:用于分支跳转,内部可执行多条语句,必须配END CASE - 表达式
CASE WHEN:只能返回单个值,用在SET、SELECT、INSERT ... VALUES等需要值的地方 - 混用会报错,例如在
SET var = CASE ... END里写END CASE,MySQL 直接提示ERROR 1064
正确写法:流程控制 CASE 必须带 END CASE,且每个分支非空
这是 MySQL 存储过程里真正能“分支执行”的 CASE,常用于根据输入参数做不同逻辑处理:
DELIMITER //
CREATE PROCEDURE p_status_desc(IN code INT, OUT desc_text VARCHAR(50))
BEGIN
CASE code
WHEN 0 THEN SET desc_text = '成功';
WHEN 10001 THEN SET desc_text = '用户名或密码错误';
WHEN 10002 THEN SET desc_text = '你没有对应的权限';
ELSE SET desc_text = '未知状态码';
END CASE; -- 注意这里是 END CASE,不是 END
END //
DELIMITER ;- 每个
WHEN后必须跟至少一条语句(不能空着) -
ELSE不是必须的,但不写且没匹配项时,整个CASE块会报错(不是返回 NULL) -
code和所有WHEN值类型要一致,比如都是整数,否则隐式转换失败可能跳过匹配
表达式 CASE 更常用:SET / SELECT / INSERT 中直接计算值
日常更多用的是表达式形式,简洁、可嵌套、兼容性好,比如:
SET @level = CASE WHEN @score >= 90 THEN 'A'
WHEN @score >= 80 THEN 'B'
ELSE 'C' END;- 这种写法必须以
END结尾,不是END CASE - 所有分支返回值类型要一致,比如不能有的返回字符串、有的返回数字,否则 MySQL 会强制转成字符串或报错
- 没匹配时默认返回
NULL,加ELSE才能控制默认值 - 可用于
UPDATE的SET子句:UPDATE users SET status = CASE WHEN expired=1 THEN 'inactive' ELSE 'active' END
容易踩的坑:条件顺序、类型隐式转换、嵌套层级
实际调试中最常卡在这几个点:
- 条件顺序错乱:比如先写
WHEN score > 60再写WHEN score > 80,后者永远不触发——CASE 匹配第一个为真分支就停 - 隐式类型转换失效:
CASE status WHEN '1' THEN '启用',如果status是整型字段,MySQL 可能不匹配(取决于 SQL mode),建议显式转类型或统一用数值比较 - 嵌套太深:SQL Server 限制最多 10 层嵌套,MySQL 虽无硬限制但超过 3 层就难维护,优先拆成变量或临时表
- 忘记
END:表达式 CASE 少写END报错信息很模糊,常被误判为前面某处语法问题
最麻烦的是流程控制 CASE 和表达式 CASE 混用——看着像,行为完全不同,出错时得先确认你到底想“执行代码”还是“算一个值”。

















