Mysql хранимая процедура внешнего курсора не удается зациклить - PullRequest
0 голосов
/ 29 марта 2012

Привет, у меня есть вложенный курсор с тремя уровнями на нем ...

        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 голосов
/ 26 июня 2012

Вы знаете , что каждый внешний цикл имеет , а не завершается, когда вы обрабатываете внутренний цикл (иначе вы бы не обрабатывали внутренний цикл), поэтому просто сбрасывайте v_done после каждоговнутренний цикл:

SET v_done := FALSE;

Это все, что вам нужно сделать.

Не создавайте логическую переменную для каждого курсора и копируйте значение;по логике они могут быть только true!

0 голосов
/ 26 июня 2012

Я обнаружил обходной путь: добавленные переменные предназначены для зацикливания внешнего курсора до последней строки.

  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 ;
...