• MySQL 流程控制 的详细讲解


    MySQL 流程控制 的详细讲解

    在这里插入图片描述


    每博一文案

    少有人走的路中,有这样一句话,一辈子真的很短,远没有我们想象的那么长,永远真的没有那么远。
    人这一生很短,我们需要清醒地活着。人在世上活着,会面临许多选择和决定,也会遭遇困境和疑惑。
    有人被欲望蒙蔽了双眼,做了错误的决定,遗憾终身,一个活得通透的人。
    我有这三次觉醒,人身难得而易失,良时易往而难追,人这一辈子,最大的财富是拥有一个健康的身体。
    人生的第一个觉醒:金钱永远没有健康重要。
    每个人来到世上,都是唯一的,无论用多少财富都换不来。
    金钱名利都是虚妄,生不带来,死不带去,百年之后都会烟消云散,化作黄土。叔本华曾说:
    “人类所能犯的最大错误,就是拿健康来换取其他身外之物。”世上钱多赚不完,随富随贫且随喜。
                                        ——————  一禅心灵庙语
    


    1. 流程控制的概念

    解决复杂问题不可能通过一个 SQL 语句完成,我们需要执行多个 SQL 操作。流程控制语句的作用就是 控制存储过程或存储函数 中 SQL语句的执行顺序 。是我们完成复杂操作必不可少的一部分,只要是执行的程序。

    流程就分为三大类:

    • 顺序结构: 程序从上往下依次执行
    • 分支结构:程序按条件进行选择执行,从两条或多条路径中选择一条执行
    • 循环结构: 程序满足一定条件下,重复执行一组语句

    注意: 针对于MySQL的流程控制语句主要有 3 类

    • 条件判断语句:IF语句和 CASE 语句
    • 循环语句: LOOP,WHILE 和 REPEAR 语句
    • 跳转语句: ITERATE 和 LEAVE 语句

    2. 分支结构

    2. 1 分支结构之 IF

    IF 的作用和 Java ,C语言中的 作用是一样的,表达式为真,执行IF包含的语句

    格式如下:

    IF 表达式1  THEN 表达式1为真 执行该语句
    [ELSEIF 表达式2 THEN 表达式2为真,执行该语句]
    [ELSE (上述条件都不满足)执行该语句]
    END IF; -- if 作用范围结束
    

    根据表达式的结果为 TRUEFALSE 执行相应的语句。这里 其中的“[ ] ”中的内容是可选的,

    特点:1. 不同的表达式对应不同的操作,2.使用在 begin...end

    一选一,满足条件为真,执行

    -- 一选一,满足条件执行
    DELIMITER $
    CREATE PROCEDURE test_if1()
    BEGIN
         -- 声明局部变量,局部变量必须在begin...end最开始位置声明
         DECLARE stu_name VARCHAR(15); -- 没有default 默认是 null
         
         IF stu_name IS NULL 
            THEN SELECT 'stu_name is null';
         END IF; -- if 作用域结束 
    
    END $
    DELIMITER ;
    
    -- 调用存储过程
    CALL test_if1();
    

    在这里插入图片描述


    二选一,满足条件为真,执行

    -- 二选一,满足条件执行
    DELIMITER $
    CREATE PROCEDURE test_if2()
    BEGIN
         -- 声明局部变量,局部变量必须在begin...end最开始位置声明
         DECLARE stu_name VARCHAR(15) DEFAULT 'hello'; -- default设定默认值
         
         IF stu_name IS NULL 
            THEN SELECT 'stu_name is null';
         ELSE -- 否则
            SELECT 'stu_name is not null ';
         END IF; -- if 作用范围,结束
    
    END $
    DELIMITER ;
    
    -- 调用存储过程
    CALL test_if2();
    

    在这里插入图片描述


    多选一,满足条件为真,执行

    -- 多选一,满足条件执行
    DELIMITER $
    CREATE PROCEDURE test_if3()
    BEGIN
         -- 声明局部变量,局部变量必须在begin...end最开始位置声明
         DECLARE age INT  DEFAULT 19; -- default设定默认值
         
         IF age > 40 
            THEN SELECT '中壮年';
         ELSEIF age > 18
            THEN SELECT '青壮年';
         ELSEIF age > 8 
            THEN SELECT '青少年';
         ELSE 
            SELECT '婴幼儿';
         END IF; -- if 作用范围,结束
    
    END $
    DELIMITER ;
    
    -- 调用存储过程
    CALL test_if3();
    

    在这里插入图片描述


    举例: 声明存储过程“update_salary_by_eid3”,定义IN参数emp_id,输入员工编号。判断该员工 薪资如果低于9000元,就更新薪资为9000元;薪资如果大于等于9000元且低于10000的,但是奖金 比例为NULL的,就更新奖金比例为0.01;其他的涨薪100元。

    SELECT *
    FROM employees
    WHERE employee_id IN (102,103,104);
    

    在这里插入图片描述


    DELIMITER $
    CREATE PROCEDURE update_salary_by_eid3(IN emp_id INT)
    BEGIN
         -- 声明局部变量,必须在begin...end最开始位置
         DECLARE emp_sal DOUBLE; -- 记录员工工资
         DECLARE bonus DOUBLE; -- 记录员工的奖金率
         
         -- 赋值
         SELECT salary INTO emp_sal
         FROM employees
         WHERE employee_id = emp_id;
         
         SELECT commission_pct INTO bonus 
         FROM employees
         WHERE employee_id = emp_id;
         
         IF emp_sal < 9000
         THEN UPDATE employees
              SET salary = 9000
              WHERE employee_id = emp_id;
         ELSEIF emp_sal >= 9000 AND emp_sal < 10000 AND bonus IS NULL
         THEN UPDATE employees
              SET commission_pct = 0.01
              WHERE employee_id = emp_id;
         ELSE 
              UPDATE employees
              SET salary = salary + 100
              WHERE employee_id = emp_id;
         END IF; -- if语句作用范围,结束
    
    END $
    DELIMITER ;
    

    调用存储过程

    -- 调用存储过程
    CALL update_salary_by_eid3(102);
    

    在这里插入图片描述


    -- 调用存储过程
    CALL update_salary_by_eid3(104);
    
    SELECT *
    FROM employees
    WHERE employee_id IN (102,103,104);
    

    在这里插入图片描述


    -- 调用存储过程
    CALL update_salary_by_eid3(103);
    
    SELECT *
    FROM employees
    WHERE employee_id IN (102,103,104);
    
    

    在这里插入图片描述


    2.2 分支结构之 CASE

    分支结构 case 表示多分支结构 ,一个信息多个值,或者多个范围,多种情况

    格式如下:

    情况一:类似于 switch

    -- 情况一:类似于 switch
    CASE 表达式
    WHEN1 THEN 结果1或语句1(如果是语句,需要加上分号)
    WHEN2 THEN 结果2或语句2(如果是语句,需要加上分号)
    WHEN3 THEN 结果3或语句3(如果是语句,需要加上分号)
    END CASE; -- 如果是放在begin...end中需要加上case,如果放在select后面不需要加case)
    

    情况二: 类似于多重if

    -- 情况二: 类似于多重if
    CASE 
    WHEN 条件1 THEN 结果1或语句1(如果是语句,需要加上分号)
    WHEN 条件2 THEN 结果2或语句2(如果是语句,需要加上分号)
    WHEN 条件3 THEN 结果3或语句3(如果是语句,需要加上分号)
    END CASE; -- 如果是放在begin...end中需要加上case,如果放在select后面不需要加case)
    

    举例情况1: 创建存储过程 test_case( )

    
    DELIMITER //
    CREATE PROCEDURE test_case()
    BEGIN 
          -- 声明局部变量,必须在begin...end最开始位置
          DECLARE var INT DEFAULT 2; -- default 设定默认值
          CASE var
               WHEN 1 THEN SELECT 'var = 1'; -- 如果是语句需要加上分号
               WHEN 2 THEN SELECT 'var = 2';
               WHEN 3 THEN SELECT 'var = 3';
               ELSE SELECT 'other value';
           END CASE; -- case 作用范围结束
    
    END //
    DELIMITER ;
    
    -- 调用存储过程
    CALL test_case();
    

    在这里插入图片描述


    举例情况2 创建存储过程 test_case2( )

    
    DELIMITER $
    CREATE PROCEDURE test_case2()
    BEGIN 
         -- 声明局部变量,必须在beign...end最开始位置
         DECLARE var INT DEFAULT 10; -- defualt设定默认值为 10
         
         CASE
         WHEN var >= 100 THEN SELECT '三位数';
         WHEN var >= 10 THEN SELECT '两位数';
         ELSE SELECT '个数位';
         END CASE ; -- case 作用范围结束,case在begin...end需要指明case标签,在select 中不用
         
    END $
    DELIMITER ;
    
    -- 调用存储过程
    CALL test_case2();
    

    在这里插入图片描述


    3. 循环结构

    3.1 循环结构之LOOP

    LOOP 循环语句用来重复执行某些语句。LOOP 内的语句一直重复执行直到 循环被退出**(使用 LEAVE于Java中的 break 作用是一样的)**。跳出循环过程。其实 LOOP 和 C语言中的 goto 类似,和 Java中的 goto也类似

    LOOP语句的基本格式如下:

    xxx:LOOP -- xxx 表示标签,用于 loop 的跳转,和 leave 的跳出
    循环执行语句
    IF 条件 
    THEN LEAVE xxx; -- 跳出该 loop 循环体,xxx 表示标签
    END LOOP xxx; -- loop 作用范围,结束,xxx 表示标签
    

    举例: 使用LOOP语句进行循环操作,id值小于10时将重复执行存储函数。

    -- 存储函数的参数配置
    SET GLOBAL log_bin_trust_function_creators = 1;
    
    DELIMITER //
    CREATE FUNCTION test_loop()
    RETURNS INT -- 返回的数据类型,多个s,不要加;分号
    BEGIN 
          -- 声明局部变量,必须在begin...end最开始位置
          DECLARE num INT DEFAULT 1; -- default 设定初始值为 1
          
          loop_label:LOOP -- loop_label 标签
          
          SET num = num + 1;
          
          IF num >= 10 
          THEN LEAVE loop_label; -- levae 跳出标签loop_label循环体
          END IF; -- if作用范围,结束
          END LOOP loop_label; -- loop 作用范围,结束
          
          RETURN num; -- 返回数值
    
    END //
    DELIMITER ;
    
    -- 调用存储函数
    SELECT test_loop();
    

    在这里插入图片描述


    举例: 当市场环境变好时,公司为了奖励大家,决定给大家涨工资。声明存储过程“update_salary_loop()”,声明OUT参数num,输出循环次数。存储过程中实现循环给大家涨薪,薪资涨为 原来的1.1倍。直到全公司的平均薪资达到12000结束。并统计循环次数。

    DELIMITER $
    CREATE PROCEDURE update_salary_loop(OUT num INT)
    BEGIN
         -- 声明局部变量,必须在begin...end最开始位置
         DECLARE avg_sal DOUBLE;  -- 员工的平均工资
         DECLARE loop_count INT DEFAULT 0; -- 记录循环次数,必须赋值default 
         -- 不然默认为 null,任何数与 null 计算都为 null,无法起到累加的作用
         
         SELECT AVG(salary) INTO avg_sal
         FROM employees;
         
         loop_lable:LOOP -- loop_lable 标签,用于leave 跳出循环体
         
         IF avg_sal >= 12000
         THEN LEAVE loop_lable; -- 跳出loop_lable 循环体
         END IF; -- if 作用范围,结束
         
         UPDATE employees
         SET salary = salary * 1.1;
         
         SELECT AVG(salary) INTO avg_sal
         FROM employees;
         
         SET loop_count = loop_count + 1;
         
         END LOOP loop_lable; -- loop 作用范围,结束
         
         SET num = loop_count;
    END $
    DELIMITER ;
    
    

    调用存储过程

    -- 调用存储过程;
    SET @num = 0;
    CALL update_salary_loop(@num);
    
    SELECT @num; -- 查看会话用户变量,循环了几次
    

    在这里插入图片描述


    查询表,验证结果

    SELECT AVG(salary)
    FROM employees;
    

    在这里插入图片描述


    3.2 循环结构之WHILE

    WHILE 语句创建一个带条件判断的循环过程。WHILE 在执行语句执行时,先对指定的表达式进行判断,如果为真,就执行循环内的语句,否则退出循环。WHILE 语句的基本格式如下:

    WHILE 循环条件 DO  -- 如果循环条件结果为真,WHILE语句内的语句或语句群被执行,直
                       -- 至循环条件为假,退出循环。
    ... 循环体
    END WHILE; -- while 作用范围,结束
    

    举例: WHILE语句示例,i值小于10时,将重复执行循环过程,代码如下:

    DELIMITER $
    CREATE PROCEDURE test_while()
    BEGIN
          -- 声明局部变量,必须在begin...end最开始位置,不然报错
          DECLARE i INT DEFAULT 1; -- 必须赋予defualt 初始值,不然为null,任何数与null计算
                                   -- 都为 null,无法累加
          WHILE i <= 10 DO 
          SET i = i + 1;
          END WHILE ; -- while 作用范围,结束
          
          SELECT i;-- 查看局部变量的值,作用范围在begin...end语句块内
    
    END $
    DELIMITER ;
    
    -- 调用存储过程
    CALL test_while();
    
    

    在这里插入图片描述


    举例: 市场环境不好时,公司为了渡过难关,决定暂时降低大家的薪资。声明存储过程“update_salary_while()”,声明OUT参数num,输出循环次数。存储过程中实现循环给大家降薪,薪资降 为原来的90%。直到全公司的平均薪资达到5000结束。并统计循环次数。

    DELIMITER //
    CREATE PROCEDURE update_salary_while(OUT num INT)
    BEGIN 
         -- 声明局部变量,必须在begin...end最开始位置,不然报错
         DECLARE avg_sal DOUBLE; -- 举例平均工资
         DECLARE while_count INT DEFAULT 0; -- 记录循环次数,
         -- 注意必须default 赋予初始值,不然为 null,任何数与 null,都为 null,无法累加
         
         -- 赋值
         SELECT AVG(salary) INTO avg_sal
         FROM employees;
         
         WHILE avg_sal >= 6000 DO
         SET while_count = while_count + 1;
         
         UPDATE employees
         SET salary = salary *0.9;
         
         SELECT AVG(salary) INTO avg_sal
         FROM employees;
         
         END WHILE; -- while 作用范围,结束
         
         SET num = while_count;
    
    END //
    
    DELIMITER;
    

    调用存储过程

    -- 调用存储过程
    SET @num = 0;
    CALL update_salary_while(@num);
    
    SELECT @num; -- 查看循环次数
    

    在这里插入图片描述


    查询验证是否成功

    SELECT AVG(salary)
    FROM employees;
    

    在这里插入图片描述


    3.3 循环结构之REPEAT

    REPEAT 语句创建一个带条件判断的循环过程。与 WHILE 循环不同的时,REPEAT 循环首先会执行一次循环,然后在 UNTIL 中进行表达式的判断,如果满足条件就退出,注意是满足条件退出,同时在 UNTIL语句的后面不要加 ;分号 。即 END REPEAT ,如果条件不满足,则会就继续执行循环,直到满足退出条件为止。

    具体格式如下:

    REPEAT 
    循环体语句
    UNTIL 结束循环的条件表达式
    END REPEAT; -- repeat 作用范围,结束
    

    **举例: ** REPEAT 语句示例,i值小于10时,将重复执行循环过程,代码如下:

    
    DELIMITER //
    CREATE PROCEDURE test_repeat()
    BEGIN
         -- 声明局部变量,必须在begin...end最开始位置,不然报错
         DECLARE i INT DEFAULT 0; -- 必须default 默认初始值,不然为 null,任何数值与 null,运算都为 null
         REPEAT 
               SET i = i + 1;
               UNTIL i >=  10 -- 满足条件跳出循环,不要加;分号
         END REPEAT; -- repeat 作用范围,结束
         
         SELECT i ; -- 查询局部变量的值,作用范围在begin...end语句块内
    END //
    DELIMITER ;
    
    -- 调用存储过程
    CALL test_repeat();
    

    在这里插入图片描述


    举例: 当市场环境变好时,公司为了奖励大家,决定给大家涨工资。声明存储过程“update_salary_repeat()”,声明OUT参数num,输出循环次数。存储过程中实现循环给大家涨薪,薪资涨 为原来的1.15倍。直到全公司的平均薪资达到13000结束。并统计循环次数。

    DELIMITER $
    CREATE PROCEDURE update_salary_repeat(OUT num INT)
    BEGIN
          -- 声明局部变量,必须在begin...end首行位置
          DECLARE avg_sal DOUBLE ; -- 记录平均工资
          DECLARE repeat_count INT DEFAULT 0; -- 记录循环次数
          -- 必须defualt 初始化默认值,不然为 null,任何数与 null运算都为 null,无法累加
          
          REPEAT 
                -- 赋值
                SELECT AVG(salary) INTO avg_sal
                FROM employees;
                
                UPDATE employees
                SET salary = salary *1.15;
                
                SET repeat_count = repeat_count + 1;
                
                UNTIL avg_sal >= 13000 -- 满足条件,退出循环,不要加分号,不然报错
          END REPEAT;  -- repeat 作用范围,结束
          
          SET num = repeat_count;
    
    END $
    DELIMITER ;
    

    调用存储过程,查询循环次数

    -- 调用存储过程
    SET @num = 0;
    CALL update_salary_repeat(@num);
    SELECT @num;
    

    在这里插入图片描述


    查询表,验证是否涨薪成功

    SELECT AVG(salary)
    FROM employees;
    

    在这里插入图片描述


    3.4 对比三种循环结构

    • 凡是循环结构,一定具备 3 个要素
    1. 初始化条件
    2. 循环条件的更新
    3. 循环结束条件
    • 这三种循环都可以省略名称,但如果循环中添加了循环控制语句(LEAVE(break)ITERATE(continue))则必须添加名称标签。
    • LOOP :一般用于实现简单的 “无限循环”
    • WHILE: 先判断后执行
    • REPEAT 先执行后判断,无论如何都会至少执行一次循环体

    4. 跳转语句

    4.1 跳转语句之LEAVE语句

    LEAVE 语句:可以用在循环语句 内,或者以 BEGINEND 包裹起来的程序体内,表示跳出循环或者跳出程序体的操作。可以把 LEAVE 理解成是 C语言中或者是Java语言中的 break

    基本格式如下

    LEAVE 标记名;
    

    LEAVE往往配合 IF条件判断一起使用。以及和BEGIN … END或循环一起被使用。

    举例: 创建存储过程 “leave_begin()”,声明INT类型的IN参数num。给BEGIN…END加标记名,并在BEGIN…END中使用IF语句判断num参数的值。

    • 如果num<=0,则使用LEAVE语句退出BEGIN…END;
    • 如果num=1,则查询“employees”表的平均薪资;
    • 如果num=2,则查询“employees”表的最低薪资;
    • 如果num>2,则查询“employees”表的最高薪资。

    IF语句结束后查询“employees”表的总人数。

    注意:使用 LEAVE 跳转语句需要定义标签

    
    DELIMITER $
    CREATE PROCEDURE leave_begin(IN num INT)
    begin_label:BEGIN  -- begin_label 是标签
                IF num < 0
                   THEN LEAVE begin_label; -- break 结束该标签下的循环
                ELSEIF num = 1
                   THEN SELECT AVG(salary)
                   FROM employees;
                ELSEIF num = 2
                   THEN SELECT MIN(salary)
                   FROM employees;
                ELSE 
                   SELECT MAX(salary)
                   FROM employees;
                END IF; -- if 作用范围,结束
                
                -- 查询总人数
                SELECT COUNT(*)
                FROM employees;
    END $
    DELIMITER ;
    
    -- 调用存储过程
    CALL leave_begin(1);
    

    在这里插入图片描述


    举例: 当市场环境不好时,公司为了渡过难关,决定暂时降低大家的薪资。声明存储过程“leave_while()”,声明OUT参数num,输出循环次数,存储过程中使用WHILE循环给大家降低薪资为原来薪资的90%,直到全公 司的平均薪资小于等于10000,并统计循环次数。

    注意:使用 LEAVE 跳转语句需要定义标签

    
    DELIMITER //
    CREATE PROCEDURE leave_while(OUT num INT)
    BEGIN
           -- 声明局部变量,必须在begin...end最开始位置,不然报错
           DECLARE avg_sal DOUBLE;  -- 记录平均工资
           DECLARE while_count INT DEFAULT 0; -- 记录循环次数,必须default 设定默认初始值,不然为 null
           
           -- 赋值
           SELECT AVG(salary) INTO avg_sal
           FROM employees;
                                              -- 任何数与 null 运算都为 null
           while_lable:WHILE TRUE DO -- true 为真,死循环
                       IF avg_sal < 10000 
                       THEN LEAVE while_lable; -- break 跳出该标签循环
                       END IF; -- if 作用范围结束
                       
                       UPDATE employees
                       SET salary = salary *0.9;
                       
                       SET while_count = while_count + 1;                    
                       
                       SELECT AVG(salary) INTO avg_sal
                       FROM employees;                  
                       
                       END WHILE while_lable ;  -- while作用范围,结束
                       
                       SET num = while_count;
    END //
    DELIMITER ;
    
    -- 调用存储过程
    SET @num = 0; -- 会话用户变量必须赋予初始值,不然报错
    CALL leave_while(@num);
    SELECT @num ;
    

    查看验证

    SELECT AVG(salary)
    FROM employees;
    

    在这里插入图片描述


    4.2 跳转语句之ITERATE语句

    ITERATE 语句:只能用在循环语句 ( LOOP,REPEAT 和 WHILE 语句) 内,表示重新开始循环,将执行顺序转到语句段开头处。可以把 ITEREATE 理解为 C语言和Java语言中的 continue 跳出本次循环。

    基本格式如下:

    ITERATE label;
    

    label参数表示循环的标志。ITERATE语句必须跟在循环标志前面。

    举例: 定义局部变量num,初始值为0。循环结构中执行num + 1操作。

    • 如果num < 10,则继续执行循环;
    • 如果num > 15,则退出循环结构;
    DELIMITER //
    CREATE PROCEDURE test_iterate()
    BEGIN 
           -- 声明局部变量,必须在begin...end最开始位置,不然报错
           DECLARE num INT DEFAULT 1; -- 必须default 不然默认为null,任何数与 null 都是null
                                      -- 就无法起到累加的效果了
           loop_label:LOOP
          
           SET num = num + 1;
           
           IF num < 10
           THEN ITERATE loop_label; -- contniue 跳过本次标签loop_label循环
           ELSEIF num > 15
                THEN LEAVE loop_label; -- break 跳出标签loop_label 循环
           END IF; -- if 作用范围,结束
           
           SELECT '尚硅谷,让天下没有难学的技术';
           
           END LOOP loop_label; -- loop 循环作用范围,结束
    END //                           
    DELIMITER ;
    
    -- 调用存储过程
    CALL test_iterate();
    

    在这里插入图片描述


    再使用 while 的循环语句实现

    
    DELIMITER //
    CREATE PROCEDURE test_while_iterate()
    BEGIN 
         -- 声明局部变量,局部变量必须在begin...end最开始位置,不然报错
         DECLARE num INT DEFAULT 0; -- 必须default设定初始值,不然为null,任何数与null 结果都为 null
         
    while_lable:WHILE TRUE DO -- true 为真,这里while 无限循环
                SET num = num +1;
                
                IF num < 10 
                THEN ITERATE while_lable; -- iterate 跳过本次 while_lable 标签循环
                ELSEIF num > 15
                THEN LEAVE while_lable;  -- leave 跳出while_lable 标签循环
                END IF; -- if 作用范围,结束
                
                SELECT '尚硅谷,让天下没有难学的技术';
    END WHILE; -- while 作用范围,结束
              
    END //
    DELIMITER ;
    
    -- 调用存储过程
    CALL test_while_iterate();
    

    在这里插入图片描述


    5. 最后:

    限于自身水平,其中存在的错误,希望大家给予指教,韩信点兵——多多益善,谢谢大家,后会有期,江湖再见 !!!


    在这里插入图片描述

  • 相关阅读:
    RK3568开发笔记(九):开发板buildroot固件调通RS485口,运行项目中RS485协议调试工具Demo
    abaqus Isight学习
    【面试题】——JavaIO篇(23题)
    HorizontalScrollView滚到当前tab,并且居中显示
    Nautilus Chain全球行分享会,上海站圆满举办
    JavaStringBuffer与StringBuilder
    10.Ribbon 源码分析(springcloud)
    Pytorch训练模型模型转Onnx推理模型及推理测试(通用全流程)
    【C++】类和对象(上)
    avue中 curd的列表配置
  • 原文地址:https://blog.csdn.net/weixin_61635597/article/details/127106375