快上车,MySQL流程控制大总结

337 阅读5分钟
  • 携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第7天.

在这里插入图片描述

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 表达式
WHEN1 THEN 结果1或语句1(如果是语句,需要加分号) 
WHEN2 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 ;

爱在结尾:流程控制确实很多,不能背,遇到不会的就回来看博客,做到熟能生巧。分为三类:1、判断 ; 2、循环 ; 3、类似于break和continue的leave、iterate