游标过程详解
以上⾯的⽰例代码为例,咱们来看⼀下游标的详细执⾏过程。
游标中有个指针,当打开游标的时候,才会执⾏游标对应的select语句,这个指针会指向
select结果中第⼀⾏记录。当调⽤fetch 游标名称时,会获取当前⾏的数据,如果当前⾏⽆数据,会触发NOT FOUND
异常。
当触发NOT FOUND异常的时候,我们可以使⽤⼀个变量来标记⼀下,如下代码:
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done=TRUE;
当游标⽆数据触发NOT FOUND异常的时候,将变量v_down的值置为TURE,循环中就可以
通过v_down的值控制循环的退出。
如果当前⾏有数据,则将当前⾏数据存到对应的变量中,并将游标指针指向下⼀⾏数据,
如下语句:
fetch 游标名称 into 变量列表;
嵌套游标
写个存储过程,遍历test2、test3,将test2中的a字段和test3中的b字段任意组
合,插⼊到test1表中。
创建存储过程:
/*删除存储过程*/
DROP PROCEDURE IF EXISTS proc1;
/*声明结束符为$*/
DELIMITER $
/*创建存储过程*/
CREATE PROCEDURE proc1()
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_done1的值为true,可以v_done1来判断游标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_done1来判断游标是否结束了,退出循环*/
if v_done2 THEN
LEAVE b;
END IF;
/*将v_a、v_b插⼊test1表中*/
INSERT INTO test1 VALUES (v_a,v_b);
END LOOP b;
/*关闭cur_test2游标*/
CLOSE cur_test2;
END; END LOOP;
/*关闭游标cur_test1*/
CLOSE cur_test1;
END $
/*结束符置为;*/
DELIMITER ;
见效果:
mysql> DELETE FROM test1;
Query OK, 9 rows affected (0.00 sec)
mysql> SELECT * FROM test1;
Empty set (0.00 sec)
mysql> CALL proc1();
Query OK, 0 rows affected (0.02 sec)
mysql> SELECT * from test1;
+------+------+
| a | b |
+------+------+
| 100 | 400 |
| 100 | 500 |
| 100 | 600 |
| 200 | 400 |
| 200 | 500 |
| 200 | 600 |
| 300 | 400 |
| 300 | 500 |
| 300 | 600 |
+------+------+
9 rows in set (0.00 sec)
成功插⼊了9条数据。
总结
1. 游标⽤来对查询结果进⾏遍历处理2. 游标的使⽤过程:声明游标、打开游标、遍历游标、关闭游标
3. 游标只能在存储过程和函数中使⽤
4. ⼀个begin end中只能声明⼀个游标
5. 掌握单个游标及嵌套游标的使⽤