阅读目录:通过条件、循环语句,对处理程序进行流程控制
- 条件控制
IF条件:条件为真,执行
CASE条件:匹配到,执行
- 循环控制
WHILE循环:先判断后执行
REPEAT循环:先执行后判断
LOOP循环(死循环)
LEAVE语句(离开)
ITERATE语句:迭代,再次循环
RETURN语句:返回
注意:MySQL不支持FOR循环
一、条件控制:if语句、case语句
1 2 3 4 |
<span style="color: rgba(0, 0, 0, 1); font-size: 16px;">IF search_condition_1 THEN statement_list_1 [ELSEIF search_condition_2 THEN statement_list_2] ... [ELSE statement_list_n] END IF</span> |
如果条件search_condition_1为true,则执行相应的then子句后面的语句列表statement_list_1;
如果条件search_condition_1不为true,则判断ELSEIF子句中的条件search_condition_2是否为true,如果为true,则执行相应的then子句后面的语句列表statement_list_2;
……
如果所有的条件都不为true,则执行ELSE子句后面的语句。
例1:创建过程,判断两个输入参数哪一个大
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<span style="font-size: 16px;">mysql><span style="color: rgba(0, 0, 0, 1);"> DELIMITER $$ mysql</span>><span style="color: rgba(0, 0, 0, 1);"> CREATE PROCEDURE difference( </span>-><span style="color: rgba(0, 0, 0, 1);"> IN p1 INTEGER, </span>-><span style="color: rgba(0, 0, 0, 1);"> IN p2 INTEGER, </span>-><span style="color: rgba(0, 0, 0, 1);"> OUT p3 INTEGER) </span>-><span style="color: rgba(0, 0, 0, 1);"> BEGIN </span>-> IF p1 > p2 THEN SET p3 = <span style="color: rgba(128, 0, 128, 1);">1</span><span style="color: rgba(0, 0, 0, 1);">; </span>-> ELSEIF p1= p2 THEN SET p3 = <span style="color: rgba(128, 0, 128, 1);">2</span><span style="color: rgba(0, 0, 0, 1);">; </span>-> ELSE SET p3 = <span style="color: rgba(128, 0, 128, 1);">3</span><span style="color: rgba(0, 0, 0, 1);">; </span>-><span style="color: rgba(0, 0, 0, 1);"> END IF; </span>-><span style="color: rgba(0, 0, 0, 1);"> END $$ mysql</span>><span style="color: rgba(0, 0, 0, 1);"> DELIMITER ; mysql</span>> call difference(<span style="color: rgba(128, 0, 128, 1);">12</span>,<span style="color: rgba(128, 0, 128, 1);">56</span><span style="color: rgba(0, 0, 0, 1);">,@ax); mysql</span>> <span style="color: rgba(0, 0, 255, 1);">select</span><span style="color: rgba(0, 0, 0, 1);"> @ax; </span>+------+ | @ax | +------+ | <span style="color: rgba(128, 0, 128, 1);">3</span> | +------+</span> |
解析:输入的第一个参数对应p1,第二个对应p2,@ax用来接收输出变量p3;如果p1>p2,输出1;如果p1=p2,输出2;其他情况,输出3。
例2:创建过程,表示出players表和penalties表哪一个行数更多—>IF条件中允许包含标量子查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<span style="font-size: 16px;">mysql> create procedure `TENNIS`.`largest`(<span style="color: rgba(0, 0, 255, 1);">out</span> t <span style="color: rgba(0, 0, 255, 1);">char</span>(<span style="color: rgba(128, 0, 128, 1);">10</span><span style="color: rgba(0, 0, 0, 1);">)) </span>-><span style="color: rgba(0, 0, 0, 1);"> begin </span>-> <span style="color: rgba(0, 0, 255, 1);">if</span> (<span style="color: rgba(0, 0, 255, 1);">select</span> count(*) <span style="color: rgba(0, 0, 255, 1);">from</span> PLAYERS)>(<span style="color: rgba(0, 0, 255, 1);">select</span> count(*) <span style="color: rgba(0, 0, 255, 1);">from</span><span style="color: rgba(0, 0, 0, 1);"> PENALTIES) </span>-><span style="color: rgba(0, 0, 0, 1);"> then </span> -> <span style="color: rgba(0, 0, 255, 1);">set</span> t=<span style="color: rgba(128, 0, 0, 1);">'</span><span style="color: rgba(128, 0, 0, 1);">PLAYERS</span><span style="color: rgba(128, 0, 0, 1);">'</span><span style="color: rgba(0, 0, 0, 1);">; </span>-> elseif (<span style="color: rgba(0, 0, 255, 1);">select</span> count(*) <span style="color: rgba(0, 0, 255, 1);">from</span> PLAYERS)=(<span style="color: rgba(0, 0, 255, 1);">select</span> count(*) <span style="color: rgba(0, 0, 255, 1);">from</span><span style="color: rgba(0, 0, 0, 1);"> PENALTIES) </span>-><span style="color: rgba(0, 0, 0, 1);"> then </span> -> <span style="color: rgba(0, 0, 255, 1);">set</span> t=<span style="color: rgba(128, 0, 0, 1);">'</span><span style="color: rgba(128, 0, 0, 1);">equal</span><span style="color: rgba(128, 0, 0, 1);">'</span><span style="color: rgba(0, 0, 0, 1);">; </span>-> <span style="color: rgba(0, 0, 255, 1);">else</span> -> <span style="color: rgba(0, 0, 255, 1);">set</span> t=<span style="color: rgba(128, 0, 0, 1);">'</span><span style="color: rgba(128, 0, 0, 1);">PENALTIES</span><span style="color: rgba(128, 0, 0, 1);">'</span><span style="color: rgba(0, 0, 0, 1);">; </span>-> end <span style="color: rgba(0, 0, 255, 1);">if</span><span style="color: rgba(0, 0, 0, 1);">; </span>-><span style="color: rgba(0, 0, 0, 1);"> end $$ mysql</span>><span style="color: rgba(0, 0, 0, 1);"> delimiter ; mysql</span>><span style="color: rgba(0, 0, 0, 1);"> call largest(@lgt); mysql</span>> <span style="color: rgba(0, 0, 255, 1);">select</span><span style="color: rgba(0, 0, 0, 1);"> @lgt; </span>+---------+ | @lgt | +---------+ | PLAYERS | +---------+</span> |
1)simple case:简易case语句
1 2 3 4 5 |
<span style="color: rgba(0, 0, 0, 1); font-size: 16px;">CASE case_value WHEN when_value THEN statement_list [WHEN when_value THEN statement_list] ... [ELSE statement_list] END CASE</span> |
case_value是一个表达式,该值和每个when子句中的when_value值进行相等比较:
①如果和某个when子句中的when_value值相等,则执行相应的then子句后面的语句statement_list;
②如果没有when_value值相等,则执行else子句后面的statement_list。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<span style="font-size: 16px;">mysql><span style="color: rgba(0, 0, 0, 1);"> DELIMITER $$ mysql</span>><span style="color: rgba(0, 0, 0, 1);"> CREATE PROCEDURE p1() </span>-><span style="color: rgba(0, 0, 0, 1);"> BEGIN </span>-> DECLARE v INT DEFAULT <span style="color: rgba(128, 0, 128, 1);">3</span><span style="color: rgba(0, 0, 0, 1);">; </span>-><span style="color: rgba(0, 0, 0, 1);"> CASE v </span>-> WHEN <span style="color: rgba(128, 0, 128, 1);">2</span><span style="color: rgba(0, 0, 0, 1);"> THEN SELECT v; </span>-> WHEN <span style="color: rgba(128, 0, 128, 1);">3</span> THEN SELECT <span style="color: rgba(128, 0, 128, 1);">0</span><span style="color: rgba(0, 0, 0, 1);">; </span>-><span style="color: rgba(0, 0, 0, 1);"> ELSE </span>-><span style="color: rgba(0, 0, 0, 1);"> BEGIN </span>-><span style="color: rgba(0, 0, 0, 1);"> END </span>-><span style="color: rgba(0, 0, 0, 1);"> END CASE; </span>-><span style="color: rgba(0, 0, 0, 1);"> END </span><span style="color: rgba(0, 0, 0, 1);">$$ mysql</span>><span style="color: rgba(0, 0, 0, 1);"> DELIMITER ; mysql</span>><span style="color: rgba(0, 0, 0, 1);"> call p1(); </span>+---+ | <span style="color: rgba(128, 0, 128, 1);">0</span> | +---+ | <span style="color: rgba(128, 0, 128, 1);">0</span> | +---+</span> |
2)searched case:检索型case语句
1 2 3 4 5 |
<span style="color: rgba(0, 0, 0, 1); font-size: 16px;">CASE WHEN search_condition THEN statement_list [WHEN search_condition THEN statement_list] ... [ELSE statement_list] END CASE</span> |
对于每个when子句,判断后面的布尔表达式search_condition是否为true:
①如果某个when子句的条件为true,则执行相应的then子句后面的语句statement_list;
②如果所有的when子句的条件都不为true,则执行else后面的语句statement_list。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<span style="font-size: 16px;">mysql><span style="color: rgba(0, 0, 0, 1);"> DELIMITER $$ mysql</span>><span style="color: rgba(0, 0, 0, 1);"> CREATE PROCEDURE p2( </span>-><span style="color: rgba(0, 0, 0, 1);"> IN p1 INTEGER, </span>-><span style="color: rgba(0, 0, 0, 1);"> IN p2 INTEGER, </span>-><span style="color: rgba(0, 0, 0, 1);"> OUT p3 INTEGER) </span>-><span style="color: rgba(0, 0, 0, 1);"> BEGIN </span>-><span style="color: rgba(0, 0, 0, 1);"> CASE </span>-> WHEN p1>p2 THEN SET p3=<span style="color: rgba(128, 0, 128, 1);">1</span><span style="color: rgba(0, 0, 0, 1);">; </span>-> WHEN p1=p2 THEN SET p3=<span style="color: rgba(128, 0, 128, 1);">2</span><span style="color: rgba(0, 0, 0, 1);">; </span>-> ELSE SET p3 = <span style="color: rgba(128, 0, 128, 1);">3</span><span style="color: rgba(0, 0, 0, 1);">; </span>-><span style="color: rgba(0, 0, 0, 1);"> END CASE; </span>-><span style="color: rgba(0, 0, 0, 1);"> END$$ mysql</span>><span style="color: rgba(0, 0, 0, 1);"> DELIMITER ; mysql</span>> call p2(<span style="color: rgba(128, 0, 128, 1);">123</span>,<span style="color: rgba(128, 0, 128, 1);">321</span><span style="color: rgba(0, 0, 0, 1);">,@ax); mysql</span>> <span style="color: rgba(0, 0, 255, 1);">select</span><span style="color: rgba(0, 0, 0, 1);"> @ax; </span>+------+ | @ax | +------+ | <span style="color: rgba(128, 0, 128, 1);">3</span> | +------+</span> |
注意:
①如果在case中,没有一个when子句的比较结果为true,并且没有写else部分,那么就抛出异常:‘Case not found for CASE statement’;
②statement_list如果有多条语句,使用begin…end块包围起来(复合语句)。
二、循环控制:while循环、repeat循环、loop循环、leave语句、iterate语句
Tips:循环体结构
①条件
②SQL语句体
③程序体里面需要对条件中的变量进行处理
1 2 3 |
<span style="color: rgba(0, 0, 0, 1); font-size: 16px;">[begin_label:] WHILE search_condition DO statement_list; END WHILE [end_label];</span> |
首先判断循环开始条件search_condition是否为true(循环结束条件):
如果为true,则执行循环体中的语句statement_list。每执行完一次,都要重新判断条件search_condition是否为true;
如果条件search_condition为false,则循环结束。
特点:
先判断,后执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<span style="font-size: 16px;">mysql><span style="color: rgba(0, 0, 0, 1);"> DELIMITER $$ mysql</span>> CREATE PROCEDURE do_while(x <span style="color: rgba(0, 0, 255, 1);">int</span><span style="color: rgba(0, 0, 0, 1);">) </span>-><span style="color: rgba(0, 0, 0, 1);"> BEGIN </span>-> DECLARE v INT DEFAULT <span style="color: rgba(128, 0, 128, 1);">5</span><span style="color: rgba(0, 0, 0, 1);">; </span>-> <span style="color: rgba(0, 0, 255, 1);">set</span> v=<span style="color: rgba(0, 0, 0, 1);">x; </span>-> WHILE v><span style="color: rgba(128, 0, 128, 1);">0</span><span style="color: rgba(0, 0, 0, 1);"> DO </span>-> <span style="color: rgba(0, 0, 255, 1);">select</span><span style="color: rgba(0, 0, 0, 1);"> v; </span>-> SET v=v-<span style="color: rgba(128, 0, 128, 1);">1</span><span style="color: rgba(0, 0, 0, 1);">; </span>-><span style="color: rgba(0, 0, 0, 1);"> END WHILE; </span>-><span style="color: rgba(0, 0, 0, 1);"> END$$ mysql</span>><span style="color: rgba(0, 0, 0, 1);"> DELIMITER ; mysql</span>> call do_while(<span style="color: rgba(128, 0, 128, 1);">2</span><span style="color: rgba(0, 0, 0, 1);">); </span>+------+ | v | +------+ | <span style="color: rgba(128, 0, 128, 1);">2</span> | +------+ +------+ | v | +------+ | <span style="color: rgba(128, 0, 128, 1);">1</span> | +------+</span> |
1 2 3 4 |
<span style="color: rgba(0, 0, 0, 1); font-size: 16px;">[begin_label:] REPEAT statement_list UNTIL search_condition END REPEAT [end_label]</span> |
反复执行循环体中的语句statement_list,直到until条件search_condition 为true时,循环结束
特点:
先执行,后判断
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<span style="font-size: 16px;">mysql><span style="color: rgba(0, 0, 0, 1);"> DELIMITER $$ mysql</span>><span style="color: rgba(0, 0, 0, 1);"> CREATE PROCEDURE dorepeat(p1 INT) </span>-><span style="color: rgba(0, 0, 0, 1);"> BEGIN </span>-> SET @x=<span style="color: rgba(128, 0, 128, 1);">0</span><span style="color: rgba(0, 0, 0, 1);">; </span>-><span style="color: rgba(0, 0, 0, 1);"> REPEAT </span>-> SET @x = @x + <span style="color: rgba(128, 0, 128, 1);">1</span><span style="color: rgba(0, 0, 0, 1);">; </span>-> UNTIL @x ><span style="color: rgba(0, 0, 0, 1);"> p1 END REPEAT; </span>-><span style="color: rgba(0, 0, 0, 1);"> END$$ mysql</span>><span style="color: rgba(0, 0, 0, 1);"> DELIMITER ; mysql</span>> CALL dorepeat(<span style="color: rgba(128, 0, 128, 1);">1000</span><span style="color: rgba(0, 0, 0, 1);">); mysql</span>><span style="color: rgba(0, 0, 0, 1);"> SELECT @x; </span>+------+ | @x | +------+ | <span style="color: rgba(128, 0, 128, 1);">1001</span> | +------+</span> |
@x:用户变量,直接使用“set @x=0;”就可以生成这么一个变量,不需要数据类型,在存储过程里定义的用户变量,存储过程外面可以访问,一直被保存。
1 2 3 |
<span style="color: rgba(0, 0, 0, 1); font-size: 16px;">[begin_label:] LOOP statement_list ; END LOOP [begin_label];</span> |
反复执行循环体中的语句,直到循环结束;
循环的结束使用leave语句。
例:创建过程,等待指定的秒数后结束
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<span style="font-size: 16px;">mysql><span style="color: rgba(0, 0, 0, 1);"> delimiter $$ mysql</span>> create procedure wait_s(<span style="color: rgba(0, 0, 255, 1);">in</span> wait_seconds <span style="color: rgba(0, 0, 255, 1);">int</span><span style="color: rgba(0, 0, 0, 1);">) </span>-><span style="color: rgba(0, 0, 0, 1);"> begin </span>-> declare end_time datetime <span style="color: rgba(0, 0, 255, 1);">default</span> now() +<span style="color: rgba(0, 0, 0, 1);"> interval wait_seconds second; <span style="font-family: 'Microsoft YaHei';">#interval是间隔类型关键字 </span></span> -><span style="color: rgba(0, 0, 0, 1);"> wait_loop:loop </span>-> <span style="color: rgba(0, 0, 255, 1);">if</span> now() ><span style="color: rgba(0, 0, 0, 1);"> end_time </span>-><span style="color: rgba(0, 0, 0, 1);"> then </span>-><span style="color: rgba(0, 0, 0, 1);"> leave wait_loop; <span style="font-family: 'Microsoft YaHei';">#leave语句表离开 </span></span> -> end <span style="color: rgba(0, 0, 255, 1);">if</span><span style="color: rgba(0, 0, 0, 1);">; </span>-><span style="color: rgba(0, 0, 0, 1);"> end loop wait_loop; </span>-><span style="color: rgba(0, 0, 0, 1);"> end </span><span style="color: rgba(0, 0, 0, 1);">$$ mysql</span>><span style="color: rgba(0, 0, 0, 1);"> delimiter ; mysql</span>> call wait_x(<span style="color: rgba(128, 0, 128, 1);">10</span><span style="color: rgba(0, 0, 0, 1);">); <span style="font-family: 'Microsoft YaHei'; color: rgba(255, 0, 0, 1);">……等10秒,结束……</span></span></span> |
1 <span style="font-size: 18px; color: rgba(0, 128, 0, 1);">LEAVE label ;</span>
作用:用来退出带标签的语句块或者循环
用处:用在 BEGIN … END中或者循环中 (LOOP, REPEAT, WHILE)
例:创建过程,其中的一个语句块较早的结束
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<span style="font-size: 16px;">mysql><span style="color: rgba(0, 0, 0, 1);"> DELIMITER $$ mysql</span>><span style="color: rgba(0, 0, 0, 1);"> CREATE PROCEDURE small_exit(OUT p1 INTEGER,OUT p2 INTEGER) </span>-><span style="color: rgba(0, 0, 0, 1);"> BEGIN </span>-> SET p1 = <span style="color: rgba(128, 0, 128, 1);">1</span><span style="color: rgba(0, 0, 0, 1);">; </span>-> SET p2 = <span style="color: rgba(128, 0, 128, 1);">1</span><span style="color: rgba(0, 0, 0, 1);">; </span>-><span style="color: rgba(0, 0, 0, 1);"> block1:BEGIN </span>-><span style="color: rgba(0, 0, 0, 1);"> LEAVE block1; <span style="font-family: 'Microsoft YaHei';">#离开块block1 </span></span> -> SET p2 = <span style="color: rgba(128, 0, 128, 1);">3</span><span style="color: rgba(0, 0, 0, 1);">; <span style="font-family: 'Microsoft YaHei';">#已离开,不执行 </span></span> -><span style="color: rgba(0, 0, 0, 1);"> END block1; </span> -> SET p1 = <span style="color: rgba(128, 0, 128, 1);">4</span><span style="color: rgba(0, 0, 0, 1);">; <span style="font-family: 'Microsoft YaHei';">#执行 </span></span> -><span style="color: rgba(0, 0, 0, 1);"> END$$ mysql</span>><span style="color: rgba(0, 0, 0, 1);"> DELIMITER ; mysql</span>><span style="color: rgba(0, 0, 0, 1);"> call small_exit(@r1,@r2); mysql</span>> <span style="color: rgba(0, 0, 255, 1);">select</span><span style="color: rgba(0, 0, 0, 1);"> @r1,@r2; </span>+------+------+ | @r1 | @r2 | +------+------+ | <span style="color: rgba(128, 0, 128, 1);">4</span> | <span style="color: rgba(128, 0, 128, 1);">1</span> | +------+------+</span> |
ITERATE label;
只能出现在循环LOOP、REPEAT和WHILE 中(有标签)
含义:跳出本次循环,开始一次新的循环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<span style="font-size: 16px;">mysql><span style="color: rgba(0, 0, 0, 1);"> delimiter $$ mysql</span>><span style="color: rgba(0, 0, 0, 1);"> CREATE PROCEDURE do_iterate(p1 INT) </span>-><span style="color: rgba(0, 0, 0, 1);"> BEGIN </span>-><span style="color: rgba(0, 0, 0, 1);"> label_1: LOOP </span>-> SET p1 = p1 + <span style="color: rgba(128, 0, 128, 1);">1</span><span style="color: rgba(0, 0, 0, 1);">; </span>-> IF p1 < <span style="color: rgba(128, 0, 128, 1);">10</span><span style="color: rgba(0, 0, 0, 1);"> THEN </span><span style="color: rgba(0, 0, 0, 1);">ITERATE label_1; <span style="font-family: 'Microsoft YaHei';">#开始下一次循环 </span></span> -><span style="color: rgba(0, 0, 0, 1);"> END IF; </span>-><span style="color: rgba(0, 0, 0, 1);"> LEAVE label_1; </span>-><span style="color: rgba(0, 0, 0, 1);"> END LOOP label_1; </span>-> SET @x =<span style="color: rgba(0, 0, 0, 1);"> p1; </span>-><span style="color: rgba(0, 0, 0, 1);"> END</span><span style="color: rgba(0, 0, 0, 1);">$$ mysql</span>><span style="color: rgba(0, 0, 0, 1);"> delimiter ; mysql</span>> call do_iterate(<span style="color: rgba(128, 0, 128, 1);">1</span><span style="color: rgba(0, 0, 0, 1);">); mysql</span>> <span style="color: rgba(0, 0, 255, 1);">select</span><span style="color: rgba(0, 0, 0, 1);"> @x; </span>+------+ | @x | +------+ | <span style="color: rgba(128, 0, 128, 1);">10</span> | +------+<span style="font-family: 'Microsoft YaHei'; line-height: 1.5; background-color: rgba(255, 255, 255, 1);"> </span></span> |