1、前言
流程控制语句的作用是控制存储过程中 SQL 语句的执行顺序,是我们完成复杂操作必不可少的一部分。只要是执行的程序,流程就分为三大类:
顺序结构:程序从上往下依次执行
分支结构:程序按条件进行选择执行,从两条或多条路径中选择一条执行
循环结构:程序满足一定条件下,重复执行一组语句
针对于MySQL 的流程控制语句主要有 3 类。注意:只能用于存储程序
条件判断语句:IF 语句和 CASE 语句
循环语句:LOOP、WHILE 和 REPEAT 语句
跳转语句:ITERATE 和 LEAVE 语句
2、IF的使用
语法结构:
#“[]”中的内容是可选的 IF 表达式1 THEN 操作1 [ELSEIF 表达式2 THEN 操作2]…… [ELSE 操作N] END IF
特点: ① 不同的表达式对应不同的操作 ② 使用在begin end中
举例:
#案例1:如果val是null,就执行‘select val is null’ 如果不是 #就执行‘select val is not null ’,最后结束if语句 IF val IS NULL THEN SELECT 'val is null'; ELSE SELECT 'val is not null'; END IF;
#案例2:声明存储过程“update_salary_by_eid”,定义IN参数emp_id,输入员工编号。 #判断该员工薪资如果低于8000元并且入职时间超过5年,就涨薪500元;否则就不变。 DELIMITER $ CREATE PROCEDURE update_salary_by_eid(IN emp_id INT) BEGIN DECLARE emp_sal DOUBLE; #员工工资 DECLARE emp_date DATE; #员工入职日期 SELECT salary,hire_date INTO emp_sal,emp_date FROM employees WHERE employee_id = emp_id; IF emp_sal < 8000 AND DATEDIFF(CURDATE(),emp_date)/365 > 5 THEN UPDATE employees SET salary = salary + 500 WHERE employee_id = emp_id; END IF; END $ DELIMITER ; CALL update_salary_by_eid(104);
执行结果: 104号员工的工资从6000变到了6500
3、CASE的使用
语法结构:
#情况一:类似于switch CASE 表达式 WHEN 值1 THEN 结果1或语句1(如果是语句,需要加分号) WHEN 值2 THEN 结果2或语句2(如果是语句,需要加分号) ... ELSE 结果n或语句n(如果是语句,需要加分号) END [case](如果是放在begin end中需要加上case,如果放在select后面不需要)
#情况二:类似于多重if CASE WHEN 条件1 THEN 结果1或语句1(如果是语句,需要加分号) WHEN 条件2 THEN 结果2或语句2(如果是语句,需要加分号) ... ELSE 结果n或语句n(如果是语句,需要加分号) END [case](如果是放在begin end中需要加上case,如果放在select后面不需要)
举例:
#声明存储过程“update_salary_by_eid4”,定义IN参数emp_id,输入员工编号。 #判断该员工薪资如果低于9000元,就更新薪资为9000元; #薪资大于等于9000元且低于10000的,但是奖金比例为NULL的, #就更新奖金比例为0.01;其他的涨薪100元。 DELIMITER $ CREATE PROCEDURE update_salary_by_eid(IN emp_id INT) BEGIN DECLARE emp_sal DOUBLE; #员工工资 DECLARE emp_pct DOUBLE DEFAULT 0; #员工的奖金率 SELECT salary,commission_pct INTO emp_sal,emp_pct FROM employees WHERE employee_id = emp_id; CASE WHEN emp_sal < 9000 THEN UPDATE employees SET salary = 9000 WHERE employee_id = emp_id; WHEN 9000 <= emp_sal < 10000 AND emp_pct 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 CASE; END $ DELIMITER ; CALL update_salary_by_eid(104);
执行结果: 104号员工的工资从6500变成了9000
4、LOOP的使用
LOOP循环语句用来重复执行某些语句,语法格式: #loop_label表示LOOP语句的标注名称,该参数可以省略。 [loop_label:] LOOP 循环执行的语句(语句中包含LEAVE退出循环) END LOOP [loop_label]
举例:
#声明存储过程“update_salary_loop()”,声明OUT参数num,输出循环次数。 #存储过程中实现循环给大家涨薪,薪资涨为原来的1.1倍 #直到全公司的平均薪资达到12000结束。并统计循环次数。 DELIMITER $ CREATE PROCEDURE update_salary_loop(OUT num INT) BEGIN DECLARE count_loop INT DEFAULT 0; #执行的次数 DECLARE avg_sal DOUBLE; #员工平均工资 #开始循环 up_loop: LOOP SELECT AVG(salary) INTO avg_sal FROM employees; IF avg_sal >= 12000 THEN LEAVE up_loop; #退出循环 ELSE UPDATE employees SET salary = salary * 1.1; SET count_loop = count_loop + 1; END IF; END LOOP; #结束循环 SELECT count_loop INTO num; END $ DELIMITER ;
5、WHILE的使用
WHILE在执行语句执行时,先对指定的表达式进行判断,如果为真,就执行循环内的语句,否则退出循环,跟java中的while差不错。语法格式:
#while_label可以不写 [while_label:] WHILE 循环条件 DO 循环体 END WHILE [while_label];
举例:
#声明存储过程“update_salary_while()”,声明OUT参数num,输出循环次数。 #存储过程中实现循环给大家降薪,薪资降为原来的90%。 #直到全公司的平均薪资达到5000结束。并统计循环次数。 DELIMITER $ CREATE PROCEDURE update_salary_while(OUT num INT) BEGIN DECLARE count_while INT DEFAULT 0; #执行的次数 DECLARE avg_sal DOUBLE; #员工平均工资 SELECT AVG(salary) INTO avg_sal FROM employees; WHILE avg_sal > 5000 DO UPDATE employees SET salary = salary * 0.9; #这一步千万不要忘记写,否则会陷入死循环 SELECT AVG(salary) INTO avg_sal FROM employees; SET count_while = count_while + 1; END WHILE; #结束循环 SELECT count_while INTO num; END $ DELIMITER ;
6、REPEAT的使用
REPEAT 循环首先会执行一次循环,然后在 UNTIL 中进行表达式的判断,如果满足条件就退出,即 END REPEAT;如果条件不满足,则会就继续执行循环,直到满足退出条件为止,类似于java中的do while。
语法格式:
#repeat_label可以省略 [repeat_label:] REPEAT 循环体的语句 UNTIL 结束循环的条件表达式(注意这里没有;) END REPEAT [repeat_label]
举例:
#声明存储过程“update_salary_repeat()”,声明OUT参数num,输出循环次数。 #存储过程中实现循环给大家涨薪,薪资涨为原来的1.15倍。 #直到全公司的平均薪资达到13000结束。并统计循环次数。 DELIMITER $ CREATE PROCEDURE update_salary_repeat(OUT num INT) BEGIN DECLARE count_repeat INT DEFAULT 0; #执行的次数 DECLARE avg_sal DOUBLE; #员工平均工资 REPEAT UPDATE employees SET salary = salary * 1.15; SET count_repeat = count_repeat + 1; SELECT AVG(salary) INTO avg_sal FROM employees ; UNTIL avg_sal >= 13000 END REPEAT; #结束循环 SELECT count_repeat INTO num; END $ DELIMITER ;
7、LEAVE的使用
LEAVE语句: 可以用在循环语句内,或者以 BEGIN 和 END 包裹起来的程序体内,表示跳出循环或者跳出程序体的操作,可以把 LEAVE 理解为 break。使用跟上述LOOP中跳出循环的方式一样。
语法格式:
LEAVE 标记名
8、ITERATE的使用
ITERATE语句:只能用在循环语句(LOOP、REPEAT和WHILE语句)内,表示重新开始循环,将执行顺序转到语句段开头处。可以把 ITERATE 理解为 continue
语法格式:
#label参数表示循环的标志。ITERATE语句必须跟在循环标志前面 ITERATE label名
举例:
#定义局部变量num,初始值为0。循环结构中执行num + 1操作 #如果num < 10,则继续执行循环 #如果num > 15,则退出循环结构 DELIMITER $ CREATE PROCEDURE test() BEGIN DECLARE num INT DEFAULT 0; test_loop: LOOP SET num = num + 1; IF num < 10 THEN ITERATE test_loop; ELSEIF num > 15 THEN LEAVE test_loop; END IF; END LOOP; END $ DELIMITER ;