【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
相关推荐
༒࿈༙྇洞察༙༙྇྇࿈༒2 小时前
PostgreSQL快速入门
数据库·postgresql
携欢2 小时前
Portswigger靶场之Visible error-based SQL injection通关秘籍
数据库·sql
-XWB-3 小时前
PostgreSQL诊断系列(4/6):表空间与膨胀分析——解决“越用越大”的存储难题
数据库·postgresql
她说人狗殊途3 小时前
DDL DML DQL DCL 语句
数据库·oracle
**AE86**5 小时前
sed截取慢SQL大文件并导出指定时间范围内容
数据库·sql·sed
小清兔6 小时前
c#基础知识
开发语言·数据库·学习·unity·c#·游戏引擎·.net
喪彪6 小时前
Ubuntu操作系统下使用mysql、mongodb、redis
redis·mysql·mongodb
计算机学姐6 小时前
基于SpringBoot的社团管理系统【2026最新】
java·vue.js·spring boot·后端·mysql·spring·mybatis
天上掉下来个程小白6 小时前
微服务-25.网关登录校验-网关传递用户到微服务
java·数据库·微服务