2017-03-25 64 views
0

我有一個mysql函數將相應地更改記錄。但循環只執行一次,並留下循環與此條件。 「IF v_finished = 1 THEN LEAVE get_stock; END IF;」MYSQL循環在功能不能正常工作

但是它應該執行多次。就像在我的測試情況下,3次

BEGIN 

DECLARE P_stock int(11); 
DECLARE P_product int(11); 
DECLARE V_From_warehouse int(11); 
DECLARE V_To_warehouse int(11); 
DECLARE v_finished INTEGER DEFAULT 0; 
DECLARE V_To_warehouse_stock int(11); 
DECLARE V_From_warehouse_stock int(11); 



declare cur1 cursor for 
     SELECT material_transfer_details.product_id , material_transfer_details.quantity FROM 
      material_transfers, 
      material_transfer_details 
     WHERE 
      material_transfers.id = material_transfer_details.mtm_id 
     AND 
      material_transfers.status = 'Y' 
     AND 
      material_transfers.id = V_MTM_id; 

DECLARE CONTINUE HANDLER 
     FOR NOT FOUND SET v_finished = 1; 

SELECT warehouse_from INTO V_From_warehouse FROM material_transfers WHERE id =V_MTM_id; 

SELECT warehouse_to INTO V_To_warehouse FROM material_transfers WHERE id =V_MTM_id; 


OPEN cur1; 

get_stock: LOOP 

IF v_finished =1 THEN 
     LEAVE get_stock; 
    END IF; 

fetch cur1 into P_product , P_stock; 

SELECT quantity INTO V_To_warehouse_stock from stocks where warehouse_id = V_To_warehouse and product_id = P_product; 

SELECT quantity INTO V_From_warehouse_stock from stocks where warehouse_id = V_From_warehouse and product_id = P_product; 



IF (V_To_warehouse_stock IS NOT NULL) 
THEN 
    UPDATE 
     stocks SET quantity = quantity - P_stock 
    WHERE 
     warehouse_id = V_to_warehouse 
     AND 
      product_id = P_product; 
ELSE 

    INSERT INTO stocks(product_id , warehouse_id , quantity ,status, created_datetime , updated_datetime) values 
     (P_product , V_to_warehouse , 0-P_stock , 'Y', sysdate() , sysdate()); 


END IF; 



IF (V_From_warehouse_stock IS NOT NULL) 
THEN 
    UPDATE 
     stocks SET quantity = quantity + P_stock 
    WHERE 
     warehouse_id = V_from_warehouse 
     AND 
      product_id = P_product; 
ELSE 

    INSERT INTO stocks(product_id , warehouse_id , quantity ,status, created_datetime , updated_datetime) values 
     (P_product , V_from_warehouse , P_stock , 'Y', sysdate() , sysdate()); 


END IF; 

SET P_stock = 0; 
SET P_product = 0; 

END LOOP get_stock; 

CLOSE cur1; 




UPDATE material_transfers SET Status = 'N' WHERE id= V_MTM_id; 

UPDATE material_transfer_details SET Status = 'N' WHERE mtm_id = V_MTM_id; 

return '00000'; 

END 
+0

cur1有多少行,我的意思是選擇scrict返回任何行或不。首先檢查一次。 – Rams

+0

它返回3行。我已經手動檢查過 –

+0

「未找到的繼續處理程序」不僅會對光標起作用,而且還會在例如'SELECT warehouse_to INTO V_To_warehouse ...'沒有找到任何行 - 你顯然期望得到,因爲你在'IF(V_To_warehouse_stock IS NOT NULL)'中測試了這個行。您可以添加其他處理程序;您可以在獲取新行之前設置一個變量(這樣您可以在處理程序中檢查該變量);或其他類似的方式。 – Solarflare

回答

0

兩件事情:

首先,改變你的代碼。

get_stock: LOOP 

    SET v_finished = FALSE; 

    fetch cur1 into P_product , P_stock; 

    IF v_finished =1 THEN 
    LEAVE get_stock; 
    END IF; 

既然你在做其他的事情,可能會跳閘處理程序,重置v_finished,然後從遊標提取,並才把測試是否退出循環。按照書面的說法,如果你沒有提前處理處理程序,你應該在完全錯誤的地方進行測試,並且會留在循環中太長時間。

接下來...請確定您瞭解SELECT ... INTO。我不認爲它完全符合你的想法。

標量子查詢是一種更安全的解決方案:

SET V_To_warehouse_stock = (SELECT quantity from stocks where warehouse_id = V_To_warehouse and product_id = P_product); 

如果SELECT ... INTO未返回行,變量的值不會改變。它保留了它以前的價值,如果存在的話,那很少是你期望的。

最好避免在這樣的距離上進行鬼怪行爲,這是一個容易陷入陷阱的陷阱。

查看https://dba.stackexchange.com/a/35207/11651的效果示例。