我见过两种不同的游标处理方法是 MySQL 存储过程。MYSQLEXCEPTION
由于存储例程中的潜在风险,现在我对它们的稳定性很好奇。
假设,CURSOR
当 DBMS 引发时打开它,如果它被声明则MYSQLEXCEPTION
转到...EXIT HANDLER
方法#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
处理有点困惑。
问题:哪种方法更准确可靠?如果我不关闭CURSOR
会EXIT HANDLER
影响什么吗?如果是这样,后果可能有多“糟糕” ?
使用方法 #1:根据http://www.brainbell.com/tutorials/MySQL/Working_With_Cursors.htm
如果您没有显式关闭游标,MySQL 将在到达 END 语句时自动关闭它。