9

私のSQL:

CREATE PROCEDURE INV_MIN_PURCHASE_PRICE()
BEGIN
DECLARE done INT;
DECLARE current_inventory_ID INT;
DECLARE cur1 CURSOR FOR SELECT inventory_ID FROM _inventory;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

SET done = 0;
OPEN cur1;

REPEAT

    FETCH cur1 INTO current_inventory_ID;
    UPDATE _debug SET rows=rows+1;

UNTIL done
END REPEAT;

CLOSE cur1;

END;

このプロシージャを呼び出すと、MySQLは1行のみをフェッチしています(_debugrowsは1増加します)。なぜ??バグですか?

4

3 に答える 3

16

MySQL のストアド プロシージャで同じ問題が発生しました。特定の列に null 値を持つテーブルからすべてのレコードを取得し、別のテーブルからその値を入力することになっていました。ただし、1 つのレコードの後に​​停止しました。

CREATE PROCEDURE `updateRecord`()
    BEGIN

    DECLARE done INT DEFAULT FALSE;
    DECLARE recordId, newValue INT;
    DECLARE current_record CURSOR FOR SELECT id FROM A where b_id is null;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; 

    OPEN current_record;

    main_loop: LOOP
        FETCH current_record INTO recordId;

        IF done THEN
             LEAVE main_loop;
        END IF;

        -- fetching some value from table b
        select id into newValue from B where ...

       -- setting new value in record
       update A set b_id = newValue where id = recordId;    

      END LOOP;
    END

答えは、カーソルが行を返さなかった場合だけでなく、テーブル B の選択が行を返さなかった場合にも、「見つからないハンドラー」が実行されるということです。私の解決策は、ハンドラーによって設定された2番目の変数を使用し、選択後に「完了」変数をリセットすることでした:

    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE, noBfound = TRUE;    

           [...]

           select id into newValue from B where ...

           IF (noBfound = TRUE) THEN 
               SET done = FALSE;
           END IF;

           [...]

追加:選択後に「完了」をリセットするだけで、2番目の変数なしで実行できることは明らかです。

    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; 

           [...]

           select id into newValue from B where ...

           SET done = FALSE;

           [...]
于 2013-01-17T17:11:02.113 に答える
0

REPEATコンストラクトの代わりにLOOPを試しましたか?MySQLでうまく機能するようです。REPEAT toENDREPEATセクションを次のように置き換えます。

inv_loop: LOOP
    FETCH cur1 INTO current_inventory_ID;
    IF done = 1 THEN
        LEAVE inv_loop;
    END IF;
    UPDATE _debug SET rows=rows+1;
END LOOP;
于 2012-08-18T10:54:46.440 に答える
0
IF done THEN
         LEAVE main_loop;
ELSE
         ITERATE main_loop;
END IF;
于 2014-02-24T05:59:38.153 に答える