2017-03-25 9 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が保持する行の数は、select scrictが行を返すかどうかを意味します。最初にそれを確認してください。 – Rams

+0

3行戻っています。私は手動でそれをチェックしました –

+0

'が見つかりませんハンドラを続行する'だけでなく、カーソルに作用するだけでなく、 'SELECT warehouse_to INTO V_To_warehouse ...'は、 'IF(V_To_warehouse_stock IS NOT NULL)'でそれをテストしているので、明らかに期待している行は見つかりません。別のハンドラを追加できます。新しい行をフェッチする前に変数を設定することができます(ハンドラー内のその変数をチェックすることができます)。または他の同様の方法。 – Solarflare

答えて

0

2つのこと:

まず、あなたのコードを変更します。その後、

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を参照してください。

関連する問題