1. 前言
针对MySQL的流程控制语句主要有这三类 :
- 条件判断语句 : IF语句和CASE语句.
- 循环语句 : LOOP, WHILE, REPEAT语句.
- 跳转语句 : LEAVE与ITERATE语句.
2. 分支结构IF
(1). 语法结构
IF 表达式1 THEN 操作1 [ELSEIF 表达式2 THEN 操作2]…… [ELSE 操作N]END IF
类似Java中的if elseif else语句.
(2). 特点
- 不同表达式对应不同的操作.
- 必须使用在存储函数/存储过程中的BEGIN ... END语块中. 不能直接在普通的SQL查询语句中使用.
3. 分支结构之CASE
(1). 语法结构
情况一 :
类似Java的Switch(表达式) case.
CASE 表达式 WHEN 值1 THEN 结果1或语句1(如果是语句,需要加分号) WHEN 值2 THEN 结果2或语句2(如果是语句,需要加分号) ... ELSE 结果n或语句n(如果是语句,需要加分号) END [case](如果是放在begin end中需要加上case,如果放在select后面不需要)
情况2 :
类似java中多层if.
CASE WHEN 条件1 THEN 结果1或语句1(如果是语句,需要加分号) WHEN 条件2 THEN 结果2或语句2(如果是语句,需要加分号) ... ELSE 结果n或语句n(如果是语句,需要加分号) END [case];(如果是放在begin end中需要加上case,如果放在select后面不需要)
(2). 例
例1 : 使用CASE情况1
例2 : 使用CASE情况2
4. 循环结构之LOOP
LOOP循环语句用来执行重复执行某些语句. LOOP内的语句一直执行直到循环终止(LEAVE语句).
(1). 格式 :
[add_loop]:LOOP # 循环体 LEAVE [add_loop]; # LEAVE跳出循环 END LOOP [add_loop]; # [add_loop]为LOOP循环的标签名称, 可以省略;
(2). 例 :
- 标注名称add_loop有点类似于Java语言中的goto语句.
5.循环结构之WHILE
WHILE语句创建一个带条件判断的循环过程,条件判断为真,继续循环,否则退出循环.
(1). 格式
[while_label] : WHILE 条件 DO 循环体 END WHILE [while_label];
- while_label为循环标签名.
(2). 例 :
- WHILE循环语句类似于Java中的while语句.
6. 循环结构之REPEAT
REPEAT与WHILE不同的一点时,REPEAT首先会进行一次循环过程(WHILE语句是首先进行条件判断),然后再判断条件是否为真,条件判断在UNTIL语句中,如果满足条件,继续循环,否则退出.
由此看出,REPEAT语句类似于Java中的do-while循环.
(1). 格式
[repeat_label] : REPEAT 循环体 UNTIL 条件判断语句没有分号 END REPEAT [repeat_label];
(2). 例
7. 跳转语句之LEAVE与ITERATE
(1). LEAVE
可以用在循环语句/BEGIN END包裹的SQL语块中.表示跳出循环/跳出程序体的操作.类似于Java语言中的break.
另外,LEAVE可以与标记名搭配.
标记名: BEGIN SQL语块 END;
(2). ITERATE
只能用在循环语句内表示重新开始循环,本次循环其后的SQL代码不执行.将循环顺序置于开头.类似于Java中的continue.
可以与标签名搭配.ITERATE 标签名.
8. 游标
(1). 为什么要用到游标
- 虽然我们可以用过筛选条件WHERE/HAVING或通过限定返回记录的LIMIT返回一条记录.但无法在结果集中像指针一样,向前定位一条记录,向后定位一条记录. 或者随意定位到某条记录,并对记录的数据进行处理
- 这个时候我们可以用到游标, 游标让我们能够对结果集中的每条记录进行定位,并可以对指向的记录的数据进行操作.游标让SQL这种面相集合的语言有了面向过程开发的能力.
- SQL中,游标是一种临时的数据库对象,可以指向存储在数据库表中的数据行指针.这里游标充当指针的作用.
- MySQL中游标可以在存储过程与存储函数中使用.
(2). 游标的使用
- 游标必须声明在处理程序之前被声明,并且变量和条件必须在声明游标或处理程序前被声明.
- 使用游标一般需要经历四个操作步骤.
(3). 操作步骤
(1). 声明游标
DECLARE cur_name CURSOR FOR select_statement;
使用SELECT获取数据结果集.此时还没有开始遍历.
(2). 打开游标
OPEN cur_name;
当我们定义好游标后,如果想使用游标,必须先打开游标.打开游标时SELECT语句的查询结果集就会送到游标工作区,为后面游标逐条读取结果集的记录做准备.
(3). 使用游标
FETCH cur_name INTO var_name, var1_name...
使用游标读取当前行,并将数据保存到当前变量中.游标指针指向下一行.当游标读取的数据行有多个列名时,则在INTO关键字后面赋值给多个变量即可.
游标的查询结果集中的字段数,必须和跟在INTO后面的变量数一致. 否则MySQL会报错.
(4). 关闭游标
CLOSE cur_name;
当使用完而且不再需要使用游标时,可以考虑关掉游标. 因为游标占据系统资源.如果不及时关闭,游标一直会保持到存储过程结束,影响运行效率.
(5). 例
# 创建存储过程“get_count_by_limit_total_salary()”, # 声明IN参数 limit_total_salary,DOUBLE类型;声明 # OUT参数total_count,INT类型。 # 函数的功能可以实现累加薪资最高的几个员工的薪资值, # 直到薪资总和达到limit_total_salary参数的值, # 返回累加的人数给total_count。 CREATE PROCEDURE get_count_by_limit_total_salary(IN limit_total_salary DOUBLE, OUT total_count INT) BEGIN # 累加的总薪资 DECLARE sum_salary DOUBLE DEFAULT 0.0; # 累加的总人头数 DECLARE sum_count INT DEFAULT 0; # 从游标中获取的值 DECLARE cur_salary DOUBLE; # 创建游标 DECLARE emp_cursor CURSOR FOR SELECT salary FROM employees ORDER BY salary DESC; # 打开游标 OPEN emp_cursor; WHILE sum_salary < limit_total_salary DO SET sum_count = sum_count + 1; FETCH emp_cursor INTO cur_salary; SET sum_salary = sum_salary + cur_salary; END WHILE; SET total_count = sum_count; END; CALL get_count_by_limit_total_salary(20000, @count); SELECT @count;
(4). 小结
- 游标是MySQL中的一个重要功能. 为逐条读取结果集中的数据提供了解决方案.游标可以在存储程序中使用,效率高,代码更简洁.
- 使用游标也会带来性能问题. 在使用游标过程中,会对数据加锁,在业务并发量大时,不仅会影响业务之间的效率,还会消耗系统资源.造成内存不足.