Multiple cursors in nested loops in MySQL

前端 未结 5 553
半阙折子戏
半阙折子戏 2021-02-05 11:14

I wish to do something which appear a bit complicated in MySQL. In fact, I wish to open a cursor, do a loop, and in this loop, open a second cursor using the data from the previ

相关标签:
5条回答
  • 2021-02-05 11:38
    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 讨论(0)
  • 2021-02-05 11:39

    You need to define a new BLOCK inside your 1st cursor loop and use different Declares in that block.

    Something like:

    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 讨论(0)
  • 2021-02-05 11:39

    Or redefine the 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;          
    

    It seems that all select statements inside a loop execute the CONTINUE HANDLE

    0 讨论(0)
  • 2021-02-05 11:41

    Correct me if I'm wrong, but it looks like what you are trying to do is a bulk insert of records into your "SLA_DEMANDE_STATUS" table. Include every criteria for every indicator found and default it with the values of '0009', 'OK' and 10.0 per each indicator's Criteria ID.

    This can all be done in a single SQL-Insert. INSERT INTO ... from a SQL-Select...

    Now, if you want to only include a single "id_indicateur" entry, you can add that to the WHERE clause of the select statement.

    Notice that my SQL-Select has forced values to correspond with the columns you want to have populated. They will all be inserted to the destination table by the same name. The nice thing about this, you can just run the SQL-SELECT portion just to see the data you would EXPECT to have inserted... if its incorrect, you can adjust it to fit whatever restrictions you want.

    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 讨论(0)
  • 2021-02-05 11:46

    you could use loop,and reset the value of the handle,like this:

    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 讨论(0)
提交回复
热议问题