You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 14:25:24