MySQL嵌套游标问题:内层游标仅执行一次无法遍历所有行
嵌套游标仅执行一次的问题修复方案
你的问题根源是cur2_done变量没有在每次内层游标循环前重置为0。第一次内层游标遍历结束后,cur2_done被设为1,后续外层循环再进入内层时,这个变量还是1,直接触发退出条件,导致内层游标不再执行。
另外你的外层循环逻辑也有小问题:应该先判断cur1_done,再处理内层游标,否则最后一次FETCH到空值后,还是会执行内层逻辑,导致无效的thread_id处理。
以下是修复后的完整代码:
DELIMITER $$ USE `dum_data`$$ DROP PROCEDURE IF EXISTS `sp_process_gen`$$ CREATE DEFINER=`test`@`%` PROCEDURE `sp_process_gen`() BEGIN DECLARE cur1_done,cur2_done INT DEFAULT 0; DECLARE v_thread_id, v_id,v_tab,v_event_time INT; DECLARE v_stime,v_etime DATETIME; -- declaring cursor DECLARE cur1 CURSOR FOR SELECT thread_id FROM general_log -- WHERE thread_id in (306710429,306711335) GROUP BY thread_id; DECLARE CONTINUE HANDLER FOR NOT FOUND SET cur1_done = 1; OPEN cur1; cur1_loop: LOOP FETCH cur1 INTO v_thread_id; -- 先判断是否已经取完外层数据,避免处理空的thread_id IF cur1_done THEN CLOSE cur1; LEAVE cur1_loop; END IF; block2: BEGIN -- 每次进入内层块,重置cur2_done为0,这是关键修复点 SET cur2_done = 0; DECLARE cur2 CURSOR FOR SELECT id , event_time FROM general_log WHERE thread_id = v_thread_id ORDER BY id; DECLARE CONTINUE HANDLER FOR NOT FOUND SET cur2_done = 1; OPEN cur2; cur2_loop: LOOP FETCH cur2 INTO v_id,v_stime; IF cur2_done THEN CLOSE cur2; LEAVE cur2_loop; END IF; -- INSERT INTO aa VALUES(v_id,v_thread_id,v_stime,v_stime); INSERT INTO aa(thread_id) VALUES(v_thread_id); END LOOP cur2_loop; END block2; INSERT INTO aa(thread_id) VALUES(999999); END LOOP cur1_loop; END$$ DELIMITER ;
核心改动说明:
- 每次进入
block2时,先执行SET cur2_done = 0;,确保内层游标每次循环都从初始状态开始 - 调整外层循环中
cur1_done的判断位置,放在处理内层游标之前,避免最后一次FETCH空值后执行无效逻辑
内容的提问来源于stack exchange,提问作者Irfi
相关产品推荐
相关产品推荐

