【SQL】深入理解MySQL存储过程:MySQL流程控制语句详解

一、前置知识

  • 流程控制语句只能在 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_nameexit_loopcontinue_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 $$ 避免 ; 提前结束
变量未声明 使用 DECLAREBEGIN 后第一行声明
循环未设置退出条件 导致死循环(MySQL 会超时中断)
CASE 缺少 END CASE 语法错误,必须配对
在函数中使用 SELECT 直接输出结果集 ❌ 函数不能返回结果集,只能返回单值

七、总结对比表

语句 用途 是否必须结束条件 类似语言中的
IF 条件分支 if-else
CASE 多分支选择 switch / if-elif
WHILE 先判断后执行 while
REPEAT 先执行后判断 do-while
LOOP 自定义循环 手动 LEAVE for(;😉 / goto
相关推荐
时光追逐者28 分钟前
一款免费、简单、高效的在线数据库设计工具
数据库·mysql·oracle·sql server
another heaven29 分钟前
【软考 2026 最新版 NoSQL 数据库全分类】
数据库·nosql
满天星830357730 分钟前
【MySQL】表的操作
linux·服务器·数据库·mysql
yashuk34 分钟前
Ubuntu 系统下安装 Nginx
数据库·nginx·ubuntu
F1FJJ40 分钟前
VS Code 里管理 PostgreSQL,有哪些选择?主流扩展横向对比
网络·数据库·postgresql·容器
Bdygsl1 小时前
MySQL(8)—— 事务
数据库·mysql
IvorySQL1 小时前
直播回顾| PostgreSQL 18.3 x IvorySQL 5.3:开启 AI 数据库新纪元
数据库·postgresql·开源
编程之升级打怪1 小时前
数据库的实时同步和异步同步
数据库
captain3761 小时前
MySQL增删改查
数据库·mysql
人道领域1 小时前
Day | 12 【苍穹外卖 :导出Excel数据表】
java·后端·sql·servlet·mvc·intellij-idea