2011-05-23 28 views
14

我希望做一些在MySQL中看起來有點複雜的東西。 事實上,我希望打開一個遊標,做一個循環,然後在這個循環中,使用上一次執行的數據打開第二個遊標,然後重新循環結果。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? 如果第一個結束,第二個結束。

+2

Th at幾乎總是不正確的做事方式,而且可能無法啓動。將兩個選擇操作組合成一個語句(因此只使用一個循環);它通常會更有效率。 – 2011-05-23 15:44:33

+0

您有低利率。重要的是,您必須使用投票下方發佈答案左側的勾號標記接受的答案。這會增加你的速度。通過查看這個鏈接看看這是如何工作的:http://meta.stackoverflow.com/questions/5234/how-does-accepting-an-answer-work#5235 – Pentium10 2017-05-31 10:27:33

回答

22

您需要在第一個遊標循環中定義一個新的BLOCK,並在該塊中使用不同的聲明。

喜歡的東西:

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; 
+0

感謝分享 – 2015-03-18 13:52:17

0

糾正我,如果我錯了,但它看起來像你正在嘗試做的是記錄批量插入到你的「SLA_DEMANDE_STATUS」表。包括找到的每個指標的每個標準,並默認值爲'0009','OK'和10.0每個指標的標準ID。

這可以在一個SQL插入中完成。 INSERT INTO ... from 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 
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; 
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

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; 
+0

圍繞你的代碼的一些解釋將被視爲不錯, – zx485 2016-11-22 19:27:23