【问题标题】:MySQL Catching Exceptions in TransactionsMySQL 在事务中捕获异常
【发布时间】:2016-11-25 21:21:00
【问题描述】:

在 mysql 存储过程的事务中返回错误原因的最佳方法是什么?

这是我创建的一个存储过程。但是我注意到,如果我在语法上犯了错误,例如我忘记将 WHERE 子句放在 update 语句之一中,它只会返回 SELECT 'error' 而不是错误的实际原因发生了。

有没有更好的方法来捕捉错误,就像在你刚刚放置的 Java 中一样

catch(SQLException e){
JOptionPane.showMessageDialog(null,e.getError()+"\n"+e.getMessage() );
}

如果有任何示例或最佳做法,我将不胜感激。

CREATE DEFINER=`root`@`localhost` PROCEDURE `updateCurriculumDetails`(p_curriculumId INT, p_editedByUserId INT, p_curriculumName varchar(50), p_description VARCHAR(200), p_gradeLevelId INT, p_schoolYearId INT)
BEGIN

    DECLARE hasError BOOLEAN DEFAULT 0;
    DECLARE CONTINUE HANDLER FOR sqlexception SET hasError = 1;


    START TRANSACTION;

        UPDATE curriculum_dt c
            SET     c.`name`        = p_curriculumName, 
                    c.description   = p_description,
                    c.gradeLevelId  = p_gradeLevelId 
            WHERE   c.id            = p_curriculumId;

        UPDATE curriculum_schoolyears_dt cs
            SET     cs.schoolYearId = p_schoolYearId
            WHERE   cs.curriculumId = p_curriculumId;

        UPDATE curriculum_hd SET editedBy_UserId = p_editedByUserId,
        dateLastEdited = NOW()
            WHERE curriculumId = p_curriculumId;


    IF hasError THEN
        ROLLBACK;
        SELECT 'error';
    ELSE
        COMMIT;
        SELECT 'successfully updated' AS result;

    END IF;

END

提前致谢。

【问题讨论】:

    标签: mysql sql exception-handling transactions


    【解决方案1】:

    在这里使用CONTINUE HANDLER 是完全不合适的。您允许其余查询在发生错误后运行,这充其量是浪费时间和资源,因为您正在执行您已经知道将被回滚的查询。相反,这样的事情似乎是一个更好的计划:

    DECLARE EXIT HANDLER FOR SQLEXCEPTION
    BEGIN
      ROLLBACK;
      RESIGNAL;
    END;
    

    然而,最佳实践是不允许过程控制事务。如果调用会话已经持有一个事务,则过程中的START TRANSACTION; 将默默地隐式提交它,使调用者处于无法回滚并且不知道条件的令人羡慕的位置。

    【讨论】:

    • 感谢您的回答。在阅读了您的答案后,我意识到我只是在添加,并且在更新之后没有其他语句出现,所以我意识到没有必要像您所说的那样编写 continue 处理程序。当您说“..不允许程序控制交易”时,您能解释一下这部分吗?将事务放在存储过程中是否不可取?另外,我一直在阅读这个dev.mysql.com/doc/refman/5.5/en/error-types.html,但是当我输入“CALL mysql_errno()”时,它在工作台上返回了一个错误,它不存在。有什么方法可以打印错误? Tnx。
    • mysql_errno() 不是存储过程。它是 C 客户端库中的 C 函数(文档中使用“调用”一词意味着调用该函数,而不是 CALL 存储过程)。它用于获取实际抛出给客户端的错误——不是由处理程序捕获的错误,因此在这里对您没有帮助。如上所示使用RESIGNAL 可以让您在清理后重新抛出刚刚捕获的错误。
    • 将事务控制放在过程中并不是一个好主意,因为上面提到的原因:如果您在事务中调用这样的过程,您当前的事务将被静默提交,并且当过程完成后,您没有进行交易,但您没有意识到这一事实。希望您能看到这会如何导致意想不到的行为——就像是在远处的幽灵般的动作。
    猜你喜欢
    • 2011-10-27
    • 2015-02-27
    • 2017-01-12
    • 2015-03-02
    • 1970-01-01
    • 2013-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多