MySQL中嵌套循环中的多个游标

时间:2011-05-23 15:39:59

标签: mysql cursor

我希望做一些在MySQL中看起来有点复杂的东西。 实际上,我希望打开一个游标,做一个循环,然后在这个循环中,使用前一次执行中的数据打开第二个游标,然后重新循环结果。

  DECLARE idind INT;
  DECLARE idcrit INT;
  DECLARE idindid INT;
  DECLARE done INT DEFAULT 0;
  DECLARE done2 INT DEFAULT 0;
  DECLARE curIndicateur CURSOR FOR SELECT id_indicateur FROM indicateur;
  DECLARE curCritereIndicateur CURSOR FOR SELECT C.id_critere FROM critere C where C.id_indicateur=idind;
  DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;

  set idindid=54;
  OPEN curIndicateur;
  REPEAT
    FETCH curIndicateur INTO idind;
    open curCritereIndicateur;
    REPEAT
      FETCH curIndicateur INTO idcrit;
      INSERT INTO SLA_DEMANDE_STATUS (iddemande,idindicateur,indicateur_status,progression) values('0009',idcrit,'OK',10.0);
    UNTIL done END REPEAT;
    close curCritereIndicateur;
  UNTIL done END REPEAT;
  CLOSE curIndicateur;

事实上,对于两个游标,怎么做'直到完成',因为你只能为SQLSTATE声明一个处理程序? 如果第一个结束,第二个结束。

5 个答案:

答案 0 :(得分:23)

您需要在第一个游标循环中定义一个新的BLOCK,并在该块中使用不同的Declares。

类似的东西:

BLOCK1: begin
    declare v_col1 int;                     
    declare no_more_rows boolean1 := FALSE;  
    declare cursor1 cursor for              
        select col1
        from   MyTable;
    declare continue handler for not found  
        set no_more_rows1 := TRUE;           
    open cursor1;
    LOOP1: loop
        fetch cursor1
        into  v_col1;
        if no_more_rows1 then
            close cursor1;
            leave LOOP1;
        end if;
        BLOCK2: begin
            declare v_col2 int;
            declare no_more_rows2 boolean := FALSE;
            declare cursor2 cursor for
                select col2
                from   MyOtherTable
                where  ref_id = v_col1;
           declare continue handler for not found
               set no_more_rows2 := TRUE;
            open cursor2;
            LOOP2: loop
                fetch cursor2
                into  v_col2;
                if no_more_rows then
                    close cursor2;
                    leave LOOP2;
                end if;
            end loop LOOP2;
        end BLOCK2;
    end loop LOOP1;
end BLOCK1;

答案 1 :(得分:0)

如果我错了,请纠正我,但看起来你要做的就是在“SLA_DEMANDE_STATUS”表中大量插入记录。包括找到的每个指标的每个条件,并使用'0009','OK'和每个指标的标准ID的值默认值。

这可以在一个SQL-Insert中完成。 INSERT INTO ...来自SQL-Select ...

现在,如果您只想包含一个“id_indicateur”条目,可以将其添加到select语句的WHERE子句中。

请注意,我的SQL-Select强制值与您要填充的列相对应。它们都将以相同的名称插入目标表。关于这个的好处,你可以运行SQL-SELECT部分​​只是为了看到你要插入的数据......如果它不正确,你可以调整它以适应你想要的任何限制。

insert into SLA_DEMANDE_STATUS 
    ( iddemande,
      idindicateur,
      indicateur_status,
      progression ) 
    SELECT 
         '0009' iddemande,
         c.id_criterere idindicateur,
         'OK' indicateur_status,
         10.0 progression
       FROM 
          indicateur i;
             JOIN critere c
                ON i.id_indicateur = c.id_indicateur

答案 2 :(得分:0)

你可以使用循环,并重置句柄的值,如下所示:

get_something:loop
  open cur;
  fetch cur into temp_key;
  if no_more_record=1 then
    set no_more_record=0;
    close cur;
    leave get_something;
  else
    //do your job;
  end if;
end loop;

答案 3 :(得分:0)

或重新定义CONTINUE HANDLE:

//...
LOOP1: LOOP
      fetch cursor1
      into  v_col1;
      if no_more_rows1 then
         close cursor1;
         leave LOOP1;
      end if;
//...

      SET no_more_rows1=false;//That's new
END LOOP LOOP1;          

循环中的所有select语句似乎都执行CONTINUE HANDLE

答案 4 :(得分:0)

DECLARE _idp INT;
DECLARE _cant INT;
DECLARE _rec INT;
DECLARE done INT DEFAULT 0;
-- Definición de la consulta
DECLARE primera CURSOR FOR SELECT dp.id_prod, SUM(dp.cantidad) AS cantidad, pp.receta FROM tm_detalle_pedido AS dp INNER JOIN tm_producto_pres AS pp
DECLARE segunda CURSOR FOR SELECT id_ins, cant FROM tm_producto_ingr WHERE id_pres = _idp;

-- Declaración de un manejador de error tipo NOT FOUND
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

-- Abrimos el primer cursor
OPEN primera;

REPEAT

FETCH primera INTO _idp, _cant, _rec;

IF NOT done THEN

 OPEN segunda;
 block2: BEGIN
     DECLARE doneLangLat INT DEFAULT 0;
     DECLARE _ii INT;
     DECLARE i FLOAT;
     DECLARE _canti FLOAT;
     DECLARE CONTINUE HANDLER FOR NOT FOUND SET doneLangLat = 1;

     REPEAT
     FETCH segunda INTO _ii,_canti;
     IF NOT doneLangLat THEN
        IF _rec = 1 THEN
            SET i = _canti * _cant;
            -- Insertamos
            INSERT INTO tm_inventario (id_ins,id_tipo_ope,id_cv,cant,fecha_r) 
            VALUES (_ii, 2, @id, i, _fecha);
        END IF;
     END IF;
     UNTIL doneLangLat END REPEAT;

  END block2;
  CLOSE segunda;

 END IF;

 UNTIL done END REPEAT;
 CLOSE primera;