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 ;
我正在尝试在循环中使用游标。我遇到的问题是,无论值如何,外循环总是被执行一次,即使它应该重复多次。当我用 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 ;