LOOP 内的光标跳出过早

Cursor inside LOOP is jumping out too early

我正在尝试在循环中使用游标。我遇到的问题是,无论值如何,外循环总是被执行一次,即使它应该重复多次。当我用 select 语句替换游标时,一切正常。

要么我使用了错误的外循环,要么(可能是这种情况)我使用了错误的光标。

代码有效

CREATE PROCEDURE `OnInventoryDelete`(
    s_idProduct INT,
    s_idOrder INT,
    s_extenal_amount INT
)
BEGIN
    DECLARE loop_counter INT DEFAULT s_extenal_amount;
    
    DECLARE v_store INT;
    DECLARE v_waffle_id INT;
    
    DECLARE v_cursor_ingredientid INT;
    DECLARE v_cursor_amount INT;
    
    DECLARE v_operator VARCHAR(3) DEFAULT 'sub';
    
    DECLARE v_c_insert_done INT DEFAULT 0;
    
    DECLARE v_Ingredient_Cursor_On_Insert CURSOR FOR
        SELECT idIngredient, amount FROM WAFFLEINGREDIENT WHERE idWaffle = v_waffle_id;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_c_insert_done = TRUE;
    
    SELECT idStore INTO v_store FROM WAFFLEORDER WHERE idOrder = s_idOrder;
    SELECT idWaffle INTO v_waffle_id FROM Waffle WHERE idWaffle = s_idProduct;
    
    REPEAT
        SELECT idIngredient, amount INTO v_cursor_ingredientId, v_cursor_amount FROM  WAFFLEINGREDIENT WHERE idWaffle = v_waffle_id;
        
        CALL InventoryUpdate(v_store, v_cursor_ingredientId, v_cursor_amount, v_operator, NULL, NULL);
    
        SET loop_counter = loop_counter - 1;
    UNTIL loop_counter = 0 
    END REPEAT;
    
END //

代码无效

CREATE PROCEDURE `OnInventoryDelete`(
    s_idProduct INT,
    s_idOrder INT,
    s_extenal_amount INT
)
BEGIN
    DECLARE loop_counter INT DEFAULT s_extenal_amount;
    
    DECLARE v_store INT;
    DECLARE v_waffle_id INT;
    
    DECLARE v_cursor_ingredientid INT;
    DECLARE v_cursor_amount INT;
    
    DECLARE v_operator VARCHAR(3) DEFAULT 'sub';
    
    DECLARE v_c_insert_done INT DEFAULT 0;
    
    DECLARE v_Ingredient_Cursor_On_Insert CURSOR FOR
        SELECT idIngredient, amount FROM WAFFLEINGREDIENT WHERE idWaffle = v_waffle_id;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_c_insert_done = TRUE;
    
    SELECT idStore INTO v_store FROM WAFFLEORDER WHERE idOrder = s_idOrder;
    SELECT idWaffle INTO v_waffle_id FROM Waffle WHERE idWaffle = s_idProduct;
    
    REPEAT
        OPEN v_Ingredient_Cursor_On_Insert;
        get_ingredient : LOOP
            FETCH v_Ingredient_Cursor_On_Insert INTO v_cursor_ingredientId, v_cursor_amount;
            
            IF v_c_insert_done = 1 THEN 
                LEAVE get_ingredient; 
            END IF;
            
            -- SHOULD BE CALLED loop_counter_times
            CALL InventoryUpdate(v_store, v_cursor_ingredientId, v_cursor_amount, v_operator, NULL, NULL); 
        END LOOP get_ingredient;
        CLOSE v_Ingredient_Cursor_On_Insert;
    SET loop_counter = loop_counter - 1;
    UNTIL loop_counter = 0 
    END REPEAT;
  
END //

好的,我已经解决了我的问题,这是工作代码:

代码

CREATE PROCEDURE `OnInventoryDelete`(
    s_idProduct INT,
    s_idOrder INT,
    s_extenal_amount INT
)
BEGIN
    DECLARE loop_counter INT DEFAULT s_extenal_amount;
    DECLARE max_row INT DEFAULT 0;
    
    DECLARE v_store INT;
    DECLARE v_waffle_id INT;
    
    DECLARE v_cursor_ingredientid INT;
    DECLARE v_cursor_amount INT;
    
    DECLARE v_operator VARCHAR(3) DEFAULT 'sub';
    
    DECLARE done INT DEFAULT FALSE;
    
    DECLARE v_Ingredient_Cursor_On_Insert CURSOR FOR SELECT idIngredient, amount FROM WAFFLEINGREDIENT WHERE idWaffle = v_waffle_id;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

    SELECT idStore INTO v_store FROM WAFFLEORDER WHERE idOrder = s_idOrder;
    SELECT idWaffle INTO v_waffle_id FROM Waffle WHERE idWaffle = s_idProduct;
    
    REPEAT
    OPEN v_Ingredient_Cursor_On_Insert;
        cursor_loop : LOOP
        FETCH v_Ingredient_Cursor_On_Insert INTO v_cursor_ingredientId, v_cursor_amount;
            
        IF done THEN 
           LEAVE cursor_loop; 
        END IF;
            
        END LOOP;
    CLOSE v_Ingredient_Cursor_On_Insert;
    SELECT loop_counter;

    SET loop_counter = loop_counter - 1;
    CALL InventoryUpdate(v_store, v_cursor_ingredientId, v_cursor_amount, v_operator, NULL, NULL); 
    UNTIL loop_counter = 0 
    END REPEAT;
  
END //

DELIMITER ;