一.游标的基本使用
1.定义游标:
declare fetchSeqCursor cursor for select seqname, value from sys_sequence;
使用游标
:
open fetchSeqCursor;
fetch数据:
fetch
fetchSeqCursor
into _seqname, _value;
关闭游标:
close fetchSeqCursor;
2.遍历方式
repeat方式:
DROP PROCEDURE IF EXISTS `NestedCurosr`;
delimiter //
CREATE PROCEDURE `NestedCurosr`()
BEGIN
DECLARE Done_nested INT DEFAULT 0 ;
DECLARE i_server_idx, i_type INT default 0;
DECLARE rs_reward CURSOR FOR select id from reward_content;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET Done_nested = 1 ;
OPEN rs_reward;
REPEAT
FETCH rs_reward INTO i_type;
IF NOT Done_nested THEN
select concat(' type', i_type);
end if;
UNTIL Done_nested END REPEAT;
CLOSE rs_reward;
END //
delimiter ;
注意:假设t表有n条记录,这个循环体循环n次?
实际上是n+1次。因为到达t的最后一行的时候stopFlag还是1。这个值的修改是在下一次fetch的时候改的,但是改完后就进入begin了,没有再判断,所以会多执行一次。这多出来的一次的temp_f的值和上一次相同。
解决方法:在进入Begin之后再判断一下stopFlag的值
Loop方式:
DROP PROCEDURE IF EXISTS `NestedCurosr`;
delimiter //
CREATE PROCEDURE `NestedCurosr`()
BEGIN
DECLARE Done_nested INT DEFAULT 0 ;
DECLARE i_server_idx, i_type INT default 0;
DECLARE rs_reward CURSOR FOR select id from reward_content;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET Done_nested = 1 ;
OPEN rs_reward;
reward_loop: LOOP -- Loop through class in grade.
FETCH rs_reward INTO i_type;
IF Done_nested=1 THEN
LEAVE reward_loop;
END IF;
select concat(' type', i_type);
END LOOP reward_loop;
CLOSE rs_reward;
END //
delimiter ;
二.嵌套游标
mysql的嵌套游标的使用有别于单级游标,主要区别在于使用了不方便使用repeat方式,而是用Loop方式,上代码。
关于error handler( 注意在 Mysql 里同一个 error 的 handler 只能定义一次,多定义的话,在compile 的过程中会提示里duplicate handler defination ,所以 NOT FOUND 的 handler就只能定义一次 )。
DROP PROCEDURE IF EXISTS `NestedCurosr`;
delimiter //
CREATE PROCEDURE `NestedCurosr`()
#LANGUAGE SQL
#DETERMINISTIC
#CONTAINS SQL
#COMMENT ''
BEGIN
DECLARE Done_nested INT DEFAULT 0 ;
DECLARE i_server_idx, i_type INT default 0;
DECLARE rs_server CURSOR FOR select server_idx from server_config;
DECLARE rs_reward CURSOR FOR select id from reward_content;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET Done_nested = 1 ;
#level
OPEN rs_server;
server_loop: LOOP
FETCH NEXT FROM rs_server INTO i_server_idx;
IF Done_nested=1 THEN
LEAVE server_loop;
END IF;
select concat(' serverIdx:', i_server_idx);
OPEN rs_reward;
reward_loop: LOOP -- Loop through class in grade.
FETCH rs_reward INTO i_type;
IF Done_nested=1 THEN
LEAVE reward_loop;
END IF;
select concat(' type', i_type);
END LOOP reward_loop;
CLOSE rs_reward;
SET Done_nested=0;
END LOOP server_loop;
CLOSE rs_server;
END //
delimiter ;