Mysql存储过程外部游标无法循环

时间:2012-03-29 09:15:18

标签: mysql database stored-procedures cursor

嗨我有一个嵌套的光标,上面有三个级别......

        DECLARE campaign_csr CURSOR FOR SELECT cid FROM tempCampaign; 
        DECLARE date_csr CURSOR FOR SELECT header,ranges FROM tempDate ORDER BY id; 
        DECLARE level_csr CURSOR FOR SELECT 1st,2nd,3rd FROM tempDispoLevels ORDER BY 1st,2nd; 
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done := TRUE; 
      OPEN campaign_csr; 
           campaign_loop:LOOP 
           FETCH campaign_csr INTO xcid; 
            IF v_done THEN 
                 CLOSE campaign_csr; 
                 LEAVE campaign_loop; 
             END IF; 
select "1";
            OPEN date_csr; 
                date_loop: LOOP 
                FETCH date_csr INTO xheader,xranges; 
                 IF v_done THEN 
                 SET v_done := FALSE;
                     CLOSE date_csr; 
                    LEAVE date_loop; 
                END IF; 
select "2";
                       OPEN level_csr; 
                        level_loop: LOOP 
                        FETCH level_csr INTO x1level,x2level,x3level; 
                         IF v_done THEN 
                             SET v_done := FALSE; 
                             CLOSE level_csr; 
                            LEAVE level_loop; 
                         END IF;
select "3";
              END LOOP level_loop;
       END LOOP date_loop;
  END LOOP campaign_loop;

问题是外部循环(在本例中为campaign_loop)不会读取所有记录。有没有办法解决。 谢谢。

2 个答案:

答案 0 :(得分:0)

我发现了一个解决方法:添加的变量用于循环外部游标直到最后一行。

  1. 再声明3个v_done变量

    DECLARE v_done BOOLEAN DEFAULT FALSE; //this is the original
    DECLARE v_done1 BOOLEAN DEFAULT FALSE; //added
    DECLARE v_done2 BOOLEAN DEFAULT FALSE; //added
    DECLARE v_done3 BOOLEAN DEFAULT FALSE;//added
    
  2. 保持这一行:

    DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done := TRUE;

  3. 更改游标的每个声明:

  4.   OPEN campaign_csr;
      campaign_loop:LOOP
      FETCH campaign_csr INTO xcid; 
            IF v_done THEN 
                 CLOSE campaign_csr; 
                 LEAVE campaign_loop; 
             END IF;
    

    成:

    OPEN campaign_csr; 
               campaign_loop:LOOP 
               FETCH campaign_csr INTO xcid; 
               SET v_done1 := v_done;
                IF v_done1 THEN 
                SET v_done := FALSE; 
                     CLOSE campaign_csr; 
                     LEAVE campaign_loop; 
                 END IF;
    

    此代码适用于我。

    DELIMITER $$
    
    USE `yourDatabase`$$
    
    DROP PROCEDURE IF EXISTS `yourProcedure`$$
    
    CREATE DEFINER=`root`@`localhost` PROCEDURE `yourProcedure`()
    BEGIN 
            DECLARE xcid INT;
            DECLARE xcid2 INT;
            DECLARE xcid3 INT;
            DECLARE v_done BOOLEAN DEFAULT FALSE; 
            DECLARE v_done1 BOOLEAN DEFAULT FALSE; 
            DECLARE v_done2 BOOLEAN DEFAULT FALSE; 
            DECLARE v_done3 BOOLEAN DEFAULT FALSE; 
            DECLARE campaign_csr CURSOR FOR SELECT column FROM yourTable; 
            DECLARE date_csr CURSOR FOR SELECT column FROM yourTable2; 
            DECLARE level_csr CURSOR FOR SELECT column FROM yourTable3; 
            DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done := TRUE; 
    
            OPEN campaign_csr; 
                 campaign_loop:LOOP 
                 FETCH campaign_csr INTO xcid; 
                 SET v_done1 := v_done;
                 IF v_done1 THEN 
                    SET v_done := FALSE; 
                    CLOSE campaign_csr; 
                    LEAVE campaign_loop; 
                 END IF; 
    
                    select "1";
    
                 OPEN date_csr; 
                      date_loop: LOOP 
                      FETCH date_csr INTO xcid2; 
                  SET v_done2 := v_done;
                  IF v_done2 THEN 
                     SET v_done := FALSE; 
                         CLOSE date_csr; 
                         LEAVE date_loop; 
                      END IF;
    
                      select "2";
    
                      OPEN level_csr; 
                           level_loop: LOOP 
                           FETCH level_csr INTO xcid2; 
                       SET v_done3 := v_done;
                       IF v_done3 THEN 
                       SET v_done := FALSE; 
                                   CLOSE level_csr; 
                                   LEAVE level_loop; 
                               END IF; 
    
                      select "3";
    
                      END LOOP level_loop;
                  END LOOP date_loop;
             END LOOP campaign_loop;
    
    END$$
    
    DELIMITER ;
    

答案 1 :(得分:0)

知道当你处理内部循环时,每个外部循环都有完成(否则你不会处理内部循环),所以只需重置{{1在每个内部循环之后:

v_done

这就是你需要做的一切。

不要为每个游标创建一个布尔变量并复制该值;从逻辑上讲,它们只能是SET v_done := FALSE;