MySQL/MariaDB 流程控制语句(3)

在loop中可以使用标签来标注该循环。如果要标记loop循环,则使用"begin_label:"和"end_label",但要求begin_label和end_label是完全相同的字符串标记(或者end不用标签直接结束也可以)。

add_num: loop
    set @a=@a+1
end loop add_num;

该语句由于没有跳出循环语句,所以将会死循环。

因此,loop一般会配合leave来使用。leave的作用是退出指定标记的语句结构,一般用在循环中用来退出循环(不仅是用在loop循环,其他循环结构也一样),相当于break。因为begin...end中也能使用标记,所以leave也能用在begin...end中。 例如下面的例子,计算从1加到给定的数。通过if判断退出循环的条件,达到退出条件时使用leave来退出。

delimiter $$
create or replace procedure proc1(n int)
begin
    declare sum,i int default 0;
    loop_label: loop
        set sum=sum+i;
        if i=n then
            leave loop_label;
        end if;
        set i=i+1;
    end loop loop_label;
    select sum;
end$$
delimiter ;

call proc1(100);  /* 从1加到100 */
  sum 
--------
    5050

iterate和leave的用法一样,只不过iterate是退出当前循环直接进入下一循环。

例如下面的存储过程,它的功能是计算传入数值范围内的奇数和。当超出传入值的范围时直接退出循环,当遇到偶数时直接进入下一循环。

delimiter $$
create or replace procedure proc2(n int)
begin
    declare i,sum int default 0;
    my_loop: loop
        set i=i+1;
        if i>n then
            leave my_loop;
        elseif mod(i,2)=0 then
            iterate my_loop;
        else
            set sum=i+sum;
        end if;
    end loop;
    select sum;
end$$
delimiter ;

调用存储过程来测试。

CALL proc4(9);
  sum 
--------
      25

虽然在MariaDB中,loop能单独定义在存储程序之外,但是由于定义在外面的时候无法打标签,而退出循环的leave却必须接标签才能退出loop,因此loop定义在存储程序之外完全是一个鸡肋的功能。同理,repeat和while也是一样的。

6.repeat循环

loop循环结构中没有退出循环的条件,只能人为书写条件判断语句来判断何时退出循环。而repeat循环结构提供了直接定义退出循环条件的功能。

[begin_label:] REPEAT statement_list UNTIL search_condition END REPEAT [end_label]

其中until部分定义的是退出循环的条件。注意,until语句后面不需要结束提示符,给出了结束符反而报错。

例如下面的存储过程中,当a变量等于传入参数i的时候退出循环。

delimiter $$
create or replace procedure proc5(i int)
begin
    declare a int default 1;
    declare sum int default 1;
    addnum: repeat
        set a=a+1;
        if mod(a,2)=1 then
            set sum=sum+a;
        end if;
    until a=i
    end repeat addnum;
    select sum;
end$$
delimiter ;
call proc5(10);
  sum 
--------
      25

7.while循环

while循环和repeat循环使用方法一样,但是思路不一样。repeat是满足条件时退出,而while是满足条件时才执行循环中定义的语句。

[begin_label:] WHILE search_condition DO
statement_list
END WHILE [end_label]

例如下面的存储过程,仍然是计算传入值范围内的奇数和。但使用的是while循环。

DROP PROCEDURE IF EXISTS proc6;
DELIMITER $$
CREATE PROCEDURE proc6(i INT)
BEGIN
    SET @a=1,@sum=1;
    addnum: WHILE @a<i DO
        SET @a=@a+1;
        IF MOD(@a,2)=1 THEN
            SET @sum=@a+@sum;
        END IF;
    END WHILE addnum;
    SELECT @sum AS SUM;
END$$
DELIMITER ;

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/0a9729248bd977d48bf004fa1d411ace.html