MySQL编程进阶之:流程控制语句:`IF`、`CASE`、`LOOP`、`WHILE`和`REPEAT`在存储过程中的实践。

各位观众,欢迎来到“MySQL存储过程流程控制那些事儿”讲座现场!我是今天的“流程控制砖家”——老码。今天咱们不谈风花雪月,就聊聊MySQL存储过程中那些能让你的代码“活”起来的流程控制语句。

为什么要用流程控制?想象一下,如果你的程序只能从上到下顺序执行,那它就像一个只会直线前进的机器人,遇到点岔路口就懵圈了。流程控制语句就是给你的程序装上“大脑”,让它能根据不同的情况做出不同的选择,循环执行,重复利用,变得更加智能。

今天,老码就带大家一起拆解 IFCASELOOPWHILEREPEAT 这五大利器,让你的存储过程也能玩出花儿来!

一、IF 语句:条件判断的利器

IF 语句是流程控制中最基础,也是最常用的语句。它允许你根据一个条件的真假来执行不同的代码块。

语法结构如下:

IF condition THEN
    -- 如果 condition 为真,则执行这里的代码
ELSEIF condition2 THEN -- 可选
    -- 如果 condition2 为真,则执行这里的代码
ELSE -- 可选
    -- 如果以上条件都不满足,则执行这里的代码
END IF;

简单来说,IF 就像一个“二选一”的开关,ELSEIFELSE 就像是给这个开关增加了更多的选项。

举个栗子:判断学生成绩等级

假设我们有一个存储过程,需要根据学生的成绩来判断其等级:

DELIMITER //
CREATE PROCEDURE GetStudentGrade(IN score INT, OUT grade VARCHAR(10))
BEGIN
    IF score >= 90 THEN
        SET grade = '优秀';
    ELSEIF score >= 80 THEN
        SET grade = '良好';
    ELSEIF score >= 70 THEN
        SET grade = '中等';
    ELSEIF score >= 60 THEN
        SET grade = '及格';
    ELSE
        SET grade = '不及格';
    END IF;
END //
DELIMITER ;

-- 调用存储过程
CALL GetStudentGrade(85, @grade);
SELECT @grade; -- 输出:良好

在这个例子中,我们使用 IFELSEIFELSE 组合,根据不同的分数段设置不同的等级。

注意事项:

  • IF 语句必须以 END IF; 结束。
  • ELSEIF 可以有多个,根据实际需要添加。
  • ELSE 是可选的,如果所有条件都不满足,可以不执行任何操作。

二、CASE 语句:多条件选择的瑞士军刀

CASE 语句比 IF 语句更加灵活,它可以处理多个条件分支,并且有两种不同的使用方式:简单 CASE 和搜索 CASE。

1. 简单 CASE 语句

简单 CASE 语句将一个表达式的值与多个值进行比较,如果匹配,则执行相应的代码块。

语法结构:

CASE expression
    WHEN value1 THEN
        -- 如果 expression = value1,则执行这里的代码
    WHEN value2 THEN
        -- 如果 expression = value2,则执行这里的代码
    ELSE
        -- 如果 expression 与所有 value 都不匹配,则执行这里的代码
END CASE;

举个栗子:根据月份返回季节

DELIMITER //
CREATE PROCEDURE GetSeason(IN month INT, OUT season VARCHAR(10))
BEGIN
    CASE month
        WHEN 3 THEN SET season = '春季';
        WHEN 4 THEN SET season = '春季';
        WHEN 5 THEN SET season = '春季';
        WHEN 6 THEN SET season = '夏季';
        WHEN 7 THEN SET season = '夏季';
        WHEN 8 THEN SET season = '夏季';
        WHEN 9 THEN SET season = '秋季';
        WHEN 10 THEN SET season = '秋季';
        WHEN 11 THEN SET season = '秋季';
        WHEN 12 THEN SET season = '冬季';
        WHEN 1 THEN SET season = '冬季';
        WHEN 2 THEN SET season = '冬季';
        ELSE SET season = '未知';
    END CASE;
END //
DELIMITER ;

-- 调用存储过程
CALL GetSeason(7, @season);
SELECT @season; -- 输出:夏季

2. 搜索 CASE 语句

搜索 CASE 语句允许你在 WHEN 子句中使用更复杂的条件表达式。

语法结构:

CASE
    WHEN condition1 THEN
        -- 如果 condition1 为真,则执行这里的代码
    WHEN condition2 THEN
        -- 如果 condition2 为真,则执行这里的代码
    ELSE
        -- 如果以上条件都不满足,则执行这里的代码
END CASE;

举个栗子:根据分数范围返回等级(与 IF 示例相同)

DELIMITER //
CREATE PROCEDURE GetStudentGrade_CASE(IN score INT, OUT grade VARCHAR(10))
BEGIN
    CASE
        WHEN score >= 90 THEN SET grade = '优秀';
        WHEN score >= 80 THEN SET grade = '良好';
        WHEN score >= 70 THEN SET grade = '中等';
        WHEN score >= 60 THEN SET grade = '及格';
        ELSE SET grade = '不及格';
    END CASE;
END //
DELIMITER ;

-- 调用存储过程
CALL GetStudentGrade_CASE(85, @grade);
SELECT @grade; -- 输出:良好

可以看到,搜索 CASE 语句的功能与 IF...ELSEIF...ELSE 非常相似,但有时使用 CASE 语句可以使代码更简洁易读。

注意事项:

  • CASE 语句必须以 END CASE; 结束。
  • ELSE 子句是可选的,如果所有条件都不满足,可以不执行任何操作。
  • 在简单 CASE 语句中,expression 只会计算一次,然后与每个 value 进行比较。
  • 在搜索 CASE 语句中,每个 condition 都会被独立计算。

三、LOOP 语句:无限循环的诱惑

LOOP 语句创建一个简单的无限循环,直到你使用 LEAVE 语句显式地退出循环。

语法结构:

[loop_label:] LOOP
    -- 循环体
    IF condition THEN
        LEAVE loop_label; -- 退出循环
    END IF;
END LOOP [loop_label];

举个栗子:计算 1 到 10 的和

DELIMITER //
CREATE PROCEDURE CalculateSum(OUT sum INT)
BEGIN
    DECLARE i INT DEFAULT 1;
    SET sum = 0;

    loop_label: LOOP
        SET sum = sum + i;
        SET i = i + 1;

        IF i > 10 THEN
            LEAVE loop_label;
        END IF;
    END LOOP loop_label;
END //
DELIMITER ;

-- 调用存储过程
CALL CalculateSum(@sum);
SELECT @sum; -- 输出:55

在这个例子中,我们使用 LOOP 语句创建一个无限循环,每次循环都将 i 加到 sum 中,直到 i 大于 10,然后使用 LEAVE 语句退出循环。

注意事项:

  • LOOP 语句必须以 END LOOP; 结束。
  • LEAVE 语句必须在循环体内使用,用于退出循环。
  • loop_label 是可选的,但建议使用,可以更清晰地标识循环,并且可以在嵌套循环中使用 LEAVE 语句退出指定的循环。
  • 如果忘记使用 LEAVE 语句,将会导致无限循环,程序会一直运行下去,直到资源耗尽。

四、WHILE 语句:有条件的循环执行

WHILE 语句在条件为真时重复执行一个代码块。

语法结构:

[while_label:] WHILE condition DO
    -- 循环体
END WHILE [while_label];

举个栗子:计算 1 到 10 的和(使用 WHILE)

DELIMITER //
CREATE PROCEDURE CalculateSum_WHILE(OUT sum INT)
BEGIN
    DECLARE i INT DEFAULT 1;
    SET sum = 0;

    WHILE i <= 10 DO
        SET sum = sum + i;
        SET i = i + 1;
    END WHILE;
END //
DELIMITER ;

-- 调用存储过程
CALL CalculateSum_WHILE(@sum);
SELECT @sum; -- 输出:55

在这个例子中,我们使用 WHILE 语句,只要 i 小于等于 10,就一直执行循环体。

注意事项:

  • WHILE 语句必须以 END WHILE; 结束。
  • 在循环体中,必须确保条件最终会变为假,否则将会导致无限循环。
  • while_label 是可选的,但建议使用,可以更清晰地标识循环,并且可以在嵌套循环中使用 LEAVE 语句退出指定的循环。

五、REPEAT 语句:至少执行一次的循环

REPEAT 语句先执行一个代码块,然后检查条件,如果条件为真,则重复执行该代码块。换句话说,REPEAT 语句保证循环体至少执行一次。

语法结构:

[repeat_label:] REPEAT
    -- 循环体
UNTIL condition
END REPEAT [repeat_label];

举个栗子:计算 1 到 10 的和(使用 REPEAT)

DELIMITER //
CREATE PROCEDURE CalculateSum_REPEAT(OUT sum INT)
BEGIN
    DECLARE i INT DEFAULT 1;
    SET sum = 0;

    REPEAT
        SET sum = sum + i;
        SET i = i + 1;
    UNTIL i > 10
    END REPEAT;
END //
DELIMITER ;

-- 调用存储过程
CALL CalculateSum_REPEAT(@sum);
SELECT @sum; -- 输出:55

在这个例子中,我们使用 REPEAT 语句,先执行一次循环体,然后检查 i 是否大于 10,如果不是,则继续执行循环体。

注意事项:

  • REPEAT 语句必须以 END REPEAT; 结束。
  • 在循环体中,必须确保条件最终会变为真,否则将会导致无限循环。
  • repeat_label 是可选的,但建议使用,可以更清晰地标识循环,并且可以在嵌套循环中使用 LEAVE 语句退出指定的循环。

六、总结与对比

语句 功能 执行次数 退出方式 适用场景
IF 条件判断 0 或 1 自动退出 根据条件执行不同的代码块,适用于简单的条件分支。
CASE 多条件选择 0 或 1 自动退出 根据表达式的值或条件执行不同的代码块,适用于复杂的条件分支。
LOOP 无限循环 0 到 ∞ 使用 LEAVE 语句显式退出 需要手动控制循环次数的场景,例如读取未知数量的数据。
WHILE 条件循环 (先判断后执行) 0 到 ∞ 条件为假时自动退出 在循环开始前需要判断条件的场景,例如根据某个条件重复执行某个操作,直到条件不满足。
REPEAT 条件循环 (先执行后判断,至少执行一次) 1 到 ∞ 条件为真时自动退出 至少需要执行一次循环体的场景,例如需要先执行一次操作,然后根据结果决定是否继续执行。

七、最佳实践

  • 代码可读性: 使用适当的缩进和注释,使代码更易于理解和维护。
  • 避免无限循环: 在循环体中确保条件最终会变为真或假,避免程序陷入无限循环。
  • 使用标签: 使用标签可以更清晰地标识循环,并且可以在嵌套循环中使用 LEAVE 语句退出指定的循环。
  • 选择合适的语句: 根据实际需求选择合适的流程控制语句,例如,如果只需要简单的条件判断,可以使用 IF 语句;如果需要处理多个条件分支,可以使用 CASE 语句;如果需要重复执行某个操作,可以使用 LOOPWHILEREPEAT 语句。
  • 错误处理: 在存储过程中添加错误处理机制,例如使用 TRY...CATCH 语句,可以更好地处理异常情况,避免程序崩溃。

八、练习题

  1. 编写一个存储过程,接收一个整数作为输入,判断该整数是奇数还是偶数,并返回结果。
  2. 编写一个存储过程,接收两个整数作为输入,计算这两个整数的最大公约数(GCD)。
  3. 编写一个存储过程,接收一个整数作为输入,判断该整数是否为质数。

希望今天的讲座能帮助大家更好地理解和使用 MySQL 存储过程中的流程控制语句。记住,流程控制是让你的代码“活”起来的关键!多加练习,你也能成为流程控制的大师!

感谢大家的参与!下次再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注