Mysql游标详解
当在sql编程中需要处理一条select语句进行遍历时改如何处理?此时需要使用游标,通过游标的方式来遍历select查询的结果集来进行处理
游标的定义
游标(Cursor)是处理数据的一种方法,为了查看或者处理结果集中的数据,游标提供了在结果集中一次一行遍历数据的能力。游标只能在存储过程和函数中使用。
游标的作用
如果我们想对查询的数据进行遍历处理,此时我们就可以使用游标来进行操作。游标相当于一个指针,这个指针指向select的第一行数据,可以通过移动指针来遍历后面的数据。
游标的使用步奏
声明游标:这个过程只是创建了一个游标,需要指定这个游标需要遍历的select查询,声明游标时并不会去执行这个sql。
declare 游标名称 cursor for 查询语句;
注意: 一个begin和end中只能声明一个游标
打开游标:打开游标的时候,会执行游标对应的select语句。
open 游标名称;
遍历数据:使用游标循环遍历select结果中每一行数据,然后进行处理。
fetch 游标名称 into 变量1[,变量2,...]
取出当前行的结果,将结果放在对应的变量中,并将游标指针指向下一行的数据。
当调用fetch的时候,会获取当前行的数据
如果当前行无数据,会引发mysql内部的NOT FOUND错误。
关闭游标:游标使用完之后一定要关闭。
close 游标名称;
注意: 游标使用完毕之后一定要关闭
单游标示例
示例: 写一个函数,计算test1表中a、b字段所有的和

sql
drop function if exists fun1;
delimiter $
create function fun1(v_max_a int)
returns int
begin
#用于保存结果
declare v_total int default 0;
#创建一个变量,用于保存表中a字段的值
declare v_a int default 0;
#创建一个变量,用于保存表中b字段的值
declare v_b int default 0;
#创建一个变量,用于判断游标结束标志
declare v_done int default false;
#创建游标
declare cur_test cursor for select a,b from test1 where a <= v_max_a;
#设置游标结束v_done的值为true,v_done来判断游标是否结束
declare continue handler for not found set v_done = true;
#打开游标
open cur_test;
#遍历游标
a:loop
#获取当前行的数据,将当前行的数据放入v_a,v_b中,如果当前行无数据,v_done会被置为true
FETCH cur_test INTO v_a, v_b;
#判断
if v_done then
leave a;
end if;
#对v_total值进行累加
set v_total = v_total + v_a + v_b;
end loop a;
#关闭游标
close cur_test;
#返回结果
return v_total;
end $
delimiter ;
结果:

游标的执行过程详解
在游标中有个指针,当打开游标的时候,才会执行游标对应的select语句,这个指针会指向select结果中的第一行记录。
调用 fetch 游标名称,会获取当前行的数据,如果当前行无数据,就会触发not found异常。当触发not found异常的时候,可以使用一个变量来标记
sql
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done=TRUE;
当游标无数据触发NOT FOUND异常的时候,将变量v_down的值置为TURE,循环中就可以通过v_down的值控制循环的退出
如果当前行有数据,则将当前行数据存储到对应的变量中,并将游标指针指向下一行数据
sql
fetch 游标名称 into 变量1[,变量2,...]
嵌套游标示例
表结构:

sql
#创建一个游标存储过程
drop procedure if exists pro1;
DELIMITER $
CREATE PROCEDURE pro1()
BEGIN
#创建一个变量,用来保存当前行中a的值
DECLARE v_a int default 0;
#申明一个游标结束标志变量
DECLARE v_done1 int default false;
#创建游标
DECLARE cur_test1 cursor for select a from test2;
#设置游标结束时v_done1的值为true,可以v_done1来判断游标cur_test1是否结束了
DECLARE CONTINUE HANDLER FOR NOT FOUND set v_done1 = true;
#开启游标
open cur_test1;
#使用loop循环遍历游标
a:loop
FETCH cur_test1 into v_a;
#通过v_done1来判断游标是否结束了,退出循环
if v_done1 then
leave a;
end if;
BEGIN
#创建一个变量,用来保存当前行中b的值
DECLARE v_b int default 0;
#申明一个游标结束标志变量
DECLARE v_done2 int default false;
#创建游标
DECLARE cur_test2 cursor for select b from test3;
#设置游标结束时v_done2的值为true,可以v_done2来判断游标cur_test2是否结束了
DECLARE CONTINUE HANDLER FOR NOT FOUND set v_done2 = true;
#开启游标
open cur_test2;
#通过loop遍历循环游标
b:loop
FETCH cur_test2 into v_b;
#通过v_done2来判断游标是否结束了,退出循环
if v_done2 then
leave b;
end if;
#将v_a、v_b插入test1表
insert into test1 values (v_a,v_b);
end loop b;
#关闭游标
close cur_test2;
end;
end loop a;
/*关闭游标*/
close cur_test1;
end $
/*结束符置为;*/
DELIMITER ;
总结
1、游标是对查询结构的一种遍历方式
2、游标的使用过程:创建游标,打开游标,遍历游标,关闭游标
3、游标只能在存储过程和函数中使用
4、在begin和end只能声明一个游标
5、单游标和双游标