簡體   English   中英

MySQL存儲過程外部游標無法循環

[英]Mysql stored procedure outer cursor fails to loop

嗨,我有一個帶有三個級別的嵌套游標...

        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)無法讀取所有記錄。 有沒有辦法解決。 謝謝。

我發現了一個解決方法:添加的變量用於循環外部光標直到最后一行。

  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. 更改每個游標聲明:

  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 ;

知道在處理內部循環時每個外部循環都還沒有完成(否則您將不會處理內部循環),因此只需在每個內部循環之后重置v_done

SET v_done := FALSE;

這就是您需要做的。

不要為每個游標創建一個布爾變量並復制該值; 從邏輯上講,它們只能是true

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM