引入
我们之前学习MySQL的时候,写的语句比较简单,程序也比较单一,但是在实际开发中,解决复杂的问题是需要执行多个sql语句的,流程控制语句的作用就是用来控制存储过程中SQL语句的执行顺序。
流程分为顺序结构,分支结构和循环结构。
对应MySQL来说,流程控制语句主要有3类。
分支结构
分支结构之IF
- 语法
IF 表达式1 THEN 操作1
[ELSEIF 表达式2 THEN 操作2]……
[ELSE 操作N]
END IF
[]中的内容是可选的,根据表达式的结果为true或false来决定执行哪一个语句
使用在begin…end中或外面
声明存储过程“update_salary_by_eid1”,定义IN参数emp_id,输入员工编号。判断该员工薪资如果低于8000元并且入职时间超过5年,就涨薪500元;否则就不变。
分支结构之case
- CASE 语句的语法结构1:
#情况一:类似于switch
CASE 表达式
WHEN 值1 THEN 结果1或语句1(如果是语句,需要加分号)
WHEN 值2 THEN 结果2或语句2(如果是语句,需要加分号)
...
ELSE 结果n或语句n(如果是语句,需要加分号)
END [case](如果是放在begin end中需要加上case,如果放在select后面不需要)
- CASE 语句的语法结构2:
#情况二:类似于多重if
CASE
WHEN 条件1 THEN 结果1或语句1(如果是语句,需要加分号)
WHEN 条件2 THEN 结果2或语句2(如果是语句,需要加分号)
...
ELSE 结果n或语句n(如果是语句,需要加分号)
END [case](如果是放在begin end中需要加上case,如果放在select后面不需要)
循环结构
循环结构之loop
loop内的语句一直重复执行,直到循环被退出(使用leave子句),跳出循环过程。
语法
[loop_label:] LOOP
循环执行的语句
END LOOP [loop_label]
loop_label表示LOOP语句的标注名称,可以省略
例:id小于10时重复执行循环过程
delimiter //
create procedure test_loop()
begin
declare num int default 1;
# 起标签名
loop_label:loop
# 重新赋值
set num=num+1;
if num>=10 then leave loop_label;
end if;
end loop loop_label ;
# 查看num
select num;
end //
delimiter //;
mysql> call test_loop;
+------+
| num |
+------+
| 10 |
+------+
循环结构之while
WHILE语句创建一个带条件判断的循环过程。WHILE在执行语句执行时,先对指定的表达式进行判断,如果为真,就执行循环内的语句,否则退出循环。
WHILE语句的基本格式如下:
[while_label:] WHILE 循环条件 DO
循环体
END WHILE [while_label];
while_label为WHILE语句的标注名称
例:i值小于10时,将重复执行循环过程
DELIMITER //
CREATE PROCEDURE test_while()
BEGIN
DECLARE i INT DEFAULT 0;
WHILE i < 10 DO
SET i = i + 1;
END WHILE;
SELECT i;
END //
DELIMITER ;
#调用
CALL test_while();
mysql> CALL test_while();
+------+
| i |
+------+
| 10 |
+------+
循环结构之repeat
- REPEAT语句创建一个带条件判断的循环过程。
- 与WHILE循环不同的是,REPEAT 循环首先会执行一次循环,然后在 UNTIL 中进行表达式的判断,如果满足条件就退出,即 END REPEAT;如果条件不满足,则会就继续执行循环,直到满足退出条件为止。
- repeat类似于Java的do while
- 语法
[repeat_label:] REPEAT
循环体的语句
UNTIL 结束循环的条件表达式
END REPEAT [repeat_label]
例:
DELIMITER //
CREATE PROCEDURE test_repeat()
BEGIN
DECLARE i INT DEFAULT 0;
REPEAT
SET i = i + 1;
UNTIL i >= 10
END REPEAT;
SELECT i;
END //
DELIMITER ;
跳转语句
跳转语句之leave
- leave可以用在循环体,也可以用在begin…end中
- 表示跳出循环或跳出程序体的操作
- 可以把它理解成Java的break
- 基本语法
leave 标记名
例1:创建存储过程 “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”表的总人数。
DELIMITER //
CREATE PROCEDURE leave_begin(IN num INT)
begin_label: BEGIN
IF num<=0
THEN LEAVE begin_label;
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;
SELECT COUNT(*) FROM employees;
END //
DELIMITER ;
mysql> call leave_begin(0);
Query OK, 0 rows affected (0.00 sec)
mysql> call leave_begin(1);
+-------------+
| AVG(salary) |
+-------------+
| 6461.682243 |
+-------------+
1 row in set (0.01 sec)
+----------+
| COUNT(*) |
+----------+
| 107 |
+----------+
1 row in set (0.01 sec)
跳转语句之iterate语句
- 只能用在循环语句,表示重新开始循环,把执行顺序转到语句段开头
- 类似于Java的continue
- 语法
iterate label
-
label参数表示循环的标志。ITERATE语句必须跟在循环标志前面。
-
举例: 定义局部变量num,初始值为0。循环结构中执行num + 1操作。
- 如果num < 10,则继续执行循环;
- 如果num > 15,则退出循环结构;
DELIMITER //
CREATE PROCEDURE test_iterate()
BEGIN
DECLARE num INT DEFAULT 0;
my_loop:LOOP
SET num = num + 1;
IF num < 10
THEN ITERATE my_loop;
ELSEIF num > 15
THEN LEAVE my_loop;
END IF;
SELECT '今天又是读书的一天';
END LOOP my_loop;
END //
DELIMITER ;
mysql> call test_iterate();
+--------------------+
| 今天又是读书的一天 |
+--------------------+
| 今天又是读书的一天 |
+--------------------+
1 row in set (0.00 sec)
+--------------------+
| 今天又是读书的一天 |
+--------------------+
| 今天又是读书的一天 |
+--------------------+
1 row in set (0.00 sec)
+--------------------+
| 今天又是读书的一天 |
+--------------------+
| 今天又是读书的一天 |
+--------------------+
1 row in set (0.01 sec)
+--------------------+
| 今天又是读书的一天 |
+--------------------+
| 今天又是读书的一天 |
+--------------------+
1 row in set (0.01 sec)
+--------------------+
| 今天又是读书的一天 |
+--------------------+
| 今天又是读书的一天 |
+--------------------+
1 row in set (0.02 sec)
+--------------------+
| 今天又是读书的一天 |
+--------------------+
| 今天又是读书的一天 |
+--------------------+
1 row in set (0.02 sec)
Query OK, 0 rows affected (0.03 sec)