カーソル処理の2つの異なるアプローチはMySQLストアドプロシージャです。ストアドルーチンに潜在的なMYSQLEXCEPTION
リスクがあるため、これらの安定性に興味があります。
仮定すると、DBMSがCURSOR
を発生させ、宣言されている場合はEXIT HANDLER
に移動すると、MYSQLEXCEPTION
が開かれます...
アプローチ#1:
DELIMITER $$
CREATE PROCEDURE `test1`()
BEGIN
DECLARE `EOS` BOOLEAN DEFAULT FALSE;
DECLARE `buffer` INT UNSIGNED;
DECLARE `MyCursor` CURSOR FOR
SELECT
`id`
FROM
`MyTable`
LIMIT 50;
DECLARE EXIT HANDLER FOR MYSQLEXCEPTION
BEGIN
ROLLBACK;
SIGNAL SQLSTATE 'ERR0R' SET MESSAGE_TEXT = 'Oops... FATAL ERROR!', MYSQL_ERRNO = 5656;
END;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET `EOS` = TRUE;
START TRANSACTION;
OPEN `MyCursor`;
cycle: LOOP
FETCH `MyCursor` INTO `buffer`;
IF `EOS`
THEN LEAVE cycle;
END IF;
-- INSERTs to another tables, UPDATEs of another tables and DELETEs from to another tables
-- Section that might throw a MYSQLEXCEPTION
END LOOP cycle;
CLOSE `MyCursor`;
COMMIT;
END$$
DELIMITER ;
コメントされたセクションでMYSQLEXCEPTION
がスローされる場合、MyCursor
はおそらく閉じられないことに注意してください。 それとも、この場合、閉じられて割り当てが解除されますか?
以下のどこかで見たことがあります...
アプローチ#2:
DELIMITER $$
CREATE PROCEDURE `test2`()
BEGIN
DECLARE `EOS` BOOLEAN DEFAULT FALSE;
DECLARE `buffer` INT UNSIGNED;
DECLARE `MyCursor` CURSOR FOR
SELECT
`id`
FROM
`MyTable`
LIMIT 50;
DECLARE EXIT HANDLER FOR MYSQLEXCEPTION
BEGIN
ROLLBACK;
CLOSE `MyCursor`; -- <---- is this even needed here ?
SIGNAL SQLSTATE 'ERR0R' SET MESSAGE_TEXT = 'Oops... FATAL ERROR!', MYSQL_ERRNO = 5858;
END;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET `EOS` = TRUE;
START TRANSACTION;
OPEN `MyCursor`;
cycle: LOOP
FETCH `MyCursor` INTO `buffer`;
IF `EOS`
THEN LEAVE cycle;
END IF;
-- INSERTs to another tables, UPDATEs of another tables and DELETEs from to another tables
-- Section that might throw a MYSQLEXCEPTION
END LOOP cycle;
CLOSE `MyCursor`;
COMMIT;
END$$
DELIMITER ;
そして今、私はCURSOR
の取り扱いについて少し混乱しています。
質問:このアプローチのうち、より正確で信頼できるのはどれですか? EXIT HANDLER
でCURSOR
を閉じない場合、何か影響がありますか?そして、もしそうなら、どのように "bad"が結果であるか?
http://www.brainbell.com/tutorials/MySQL/Working_With_Cursors.htm に従ってアプローチ#1:を使用します
カーソルを明示的に閉じない場合、MySQLはENDステートメントに到達したときに自動的にカーソルを閉じます。