一、前置知识
- 流程控制语句只能在
BEGIN ... END
块中使用。 - 常用于实现条件判断、循环处理等逻辑。
- 需要配合变量使用(如
DECLARE
声明变量,SET
赋值)。
sql
DELIMITER $$
CREATE PROCEDURE 示例流程控制()
BEGIN
-- 在这里使用 IF、CASE、WHILE 等语句
END$$
DELIMITER ;
二、1. IF
语句 ------ 条件判断
✅ 语法结构:
sql
IF 条件 THEN
语句1;
[ELSEIF 条件2 THEN
语句2;]
[ELSE
其他语句;]
END IF;
🔍 示例:根据成绩判断等级
sql
DELIMITER $$
CREATE PROCEDURE GetGrade(IN score INT)
BEGIN
IF score >= 90 THEN
SELECT '优秀' AS level;
ELSEIF score >= 80 THEN
SELECT '良好' AS level;
ELSEIF score >= 60 THEN
SELECT '及格' AS level;
ELSE
SELECT '不及格' AS level;
END IF;
END$$
DELIMITER ;
-- 调用
CALL GetGrade(85); -- 输出:良好
二、2. CASE
语句 ------ 多分支选择
有两种形式:简单 CASE 和 搜索型 CASE
✅ 形式一:简单 CASE(类似 switch)
sql
CASE 变量
WHEN 值1 THEN 语句1;
WHEN 值2 THEN 语句2;
ELSE 其他语句;
END CASE;
示例:根据数字输出星期名称
sql
DELIMITER $$
CREATE PROCEDURE GetWeekday(IN day INT)
BEGIN
CASE day
WHEN 1 THEN SELECT '星期一' AS weekday;
WHEN 2 THEN SELECT '星期二' AS weekday;
WHEN 3 THEN SELECT '星期三' AS weekday;
ELSE SELECT '未知' AS weekday;
END CASE;
END$$
DELIMITER ;
CALL GetWeekday(2); -- 输出:星期二
✅ 形式二:搜索型 CASE(基于条件判断)
sql
CASE
WHEN 条件1 THEN 语句1;
WHEN 条件2 THEN 语句2;
ELSE 其他语句;
END CASE;
示例:判断年龄阶段
sql
DELIMITER $$
CREATE PROCEDURE CheckAgeGroup(IN age INT)
BEGIN
CASE
WHEN age < 13 THEN SELECT '儿童' AS group_name;
WHEN age BETWEEN 13 AND 17 THEN SELECT '青少年';
WHEN age BETWEEN 18 AND 65 THEN SELECT '成年人';
ELSE SELECT '老年人';
END CASE;
END$$
DELIMITER ;
CALL CheckAgeGroup(25); -- 输出:成年人
💡 提示:
CASE
更适合多分支选择,代码更清晰。
三、循环结构概述
MySQL 支持三种循环结构:
循环类型 | 特点 |
---|---|
WHILE |
先判断条件,再执行(可能一次都不执行) |
REPEAT |
先执行一次,再判断是否继续(至少执行一次) |
LOOP |
无条件循环,需手动 LEAVE 退出 |
所有循环都可通过 ITERATE
(继续)和 LEAVE
(跳出)控制流程。
三、1. WHILE
循环 ------ 当型循环
✅ 语法:
sql
[label:] WHILE 条件 DO
循环体语句;
END WHILE [label];
🔍 示例:计算 1 到 n 的和
sql
DELIMITER $$
CREATE PROCEDURE SumToN(IN n INT, OUT result INT)
BEGIN
DECLARE i INT DEFAULT 1;
SET result = 0;
WHILE i <= n DO
SET result = result + i;
SET i = i + 1;
END WHILE;
END$$
DELIMITER ;
-- 调用
CALL SumToN(100, @sum);
SELECT @sum; -- 输出:5050
三、2. REPEAT
循环 ------ 直到型循环(类似 do-while)
✅ 语法:
sql
[label:] REPEAT
循环体语句;
UNTIL 条件
END REPEAT [label];
⚠️ 注意:
UNTIL
后的条件为 真时退出循环
🔍 示例:打印数字直到大于 5
sql
DELIMITER $$
CREATE PROCEDURE PrintUntil5()
BEGIN
DECLARE i INT DEFAULT 1;
REPEAT
SELECT i; -- 每次输出当前 i
SET i = i + 1;
UNTIL i > 5
END REPEAT;
END$$
DELIMITER ;
CALL PrintUntil5();
-- 输出 1, 2, 3, 4, 5 (每次 SELECT 一行)
三、3. LOOP
循环 ------ 手动控制的无限循环
✅ 语法:
sql
[label:] LOOP
循环体语句;
-- 必须有 LEAVE 或 ITERATE
END LOOP [label];
控制关键字:
LEAVE label
:相当于break
,跳出循环ITERATE label
:相当于continue
,跳回循环开头
🔍 示例:使用 LOOP 计算 1~100 的和
sql
DELIMITER $$
CREATE PROCEDURE SumWithLoop(IN n INT, OUT result INT)
BEGIN
DECLARE i INT DEFAULT 1;
SET result = 0;
sum_loop: LOOP
IF i > n THEN
LEAVE sum_loop; -- 相当于 break
END IF;
SET result = result + i;
SET i = i + 1;
END LOOP sum_loop;
END$$
DELIMITER ;
CALL SumWithLoop(100, @res);
SELECT @res; -- 输出:5050
四、高级技巧:标签(Label)与流程跳转
使用标签提升可读性与控制力
sql
outer_loop: LOOP
inner_loop: WHILE i < 10 DO
IF condition THEN
LEAVE outer_loop; -- 直接跳出外层循环
END IF;
END WHILE inner_loop;
END LOOP outer_loop;
✅ 标签命名建议:
loop_name
、exit_loop
、continue_loop
等,增强可读性。
五、综合实战:生成斐波那契数列前 N 项
sql
DELIMITER $$
CREATE PROCEDURE FibSequence(IN n INT)
BEGIN
DECLARE a INT DEFAULT 0;
DECLARE b INT DEFAULT 1;
DECLARE i INT DEFAULT 1;
DECLARE temp INT;
IF n <= 0 THEN
SELECT '请输入正整数' AS msg;
ELSE
WHILE i <= n DO
SELECT a AS fibonacci; -- 输出当前项
SET temp = a + b;
SET a = b;
SET b = temp;
SET i = i + 1;
END WHILE;
END IF;
END$$
DELIMITER ;
CALL FibSequence(8);
-- 输出:0, 1, 1, 2, 3, 5, 8, 13
六、常见错误与注意事项
错误 | 解决方法 |
---|---|
忘记 DELIMITER 导致语法错误 |
使用 DELIMITER $$ 避免 ; 提前结束 |
变量未声明 | 使用 DECLARE 在 BEGIN 后第一行声明 |
循环未设置退出条件 | 导致死循环(MySQL 会超时中断) |
CASE 缺少 END CASE |
语法错误,必须配对 |
在函数中使用 SELECT 直接输出结果集 |
❌ 函数不能返回结果集,只能返回单值 |
七、总结对比表
语句 | 用途 | 是否必须结束条件 | 类似语言中的 |
---|---|---|---|
IF |
条件分支 | 否 | if-else |
CASE |
多分支选择 | 否 | switch / if-elif |
WHILE |
先判断后执行 | 是 | while |
REPEAT |
先执行后判断 | 是 | do-while |
LOOP |
自定义循环 | 手动 LEAVE |
for(;😉 / goto |