我有一个存储过程,我想在出现任何问题时回滚。为了做到这一点,我使用这样的EXIT HANDLER:
DECLARE EXIT HANDLER FOR sqlexception
begin
ROLLBACK;
end;
但是这样,当我调用这个存储过程时,如果有任何错误,存储过程成功,我不知道实际问题是什么。我希望客户端(PHP)记录错误,以便对其进行故障排除。所以我这样修改:
DECLARE EXIT HANDLER FOR sqlexception
begin
get diagnostics condition 1
@p1 = MESSAGE_TEXT;
ROLLBACK;
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @p1;
end;
所以现在存储过程回滚并抛出处理程序拦截的exeption。这很酷,但有时MESSAGE_TEXT超过128个字符,在这种情况下,我得到:
错误代码:1648。条件项目的数据太长' MESSAGE_TEXT'
当然这个解决方案是不可接受的:
DECLARE EXIT HANDLER FOR sqlexception
begin
get diagnostics condition 1
@p1 = MESSAGE_TEXT;
ROLLBACK;
SET @p1=SUBSTRING(@p1,1,128);
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @p1;
end;
有没有办法拦截任何异常,回滚然后向客户端抛出相同的异常? 非常感谢您的帮助
答案 0 :(得分:3)
根据Kenney的建议,答案是:
DECLARE EXIT HANDLER FOR sqlexception
begin
ROLLBACK;
RESIGNAL;
end;
答案 1 :(得分:1)
我使用这个模板,它适用于我。遇到异常时,事务流会立即跳转到DECLARE EXIT HANDLER FOR SQLEXCEPTION
。 MySQL引擎要执行的最后一个语句是ROLLBACK
。之后,交易流程移出tblock
通过将错误代码和消息作为记录集(不向PHP抛出错误)来优雅地处理异常,您的PHP代码可以轻松地操作和显示。< / p>
DELIMITER $$
CREATE PROCEDURE `ProcName`( <parameters here> )
BEGIN
START TRANSACTION;
tblock: BEGIN # start: transaction block
/* catch any exceptions, then rollback */
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1
@state = RETURNED_SQLSTATE,
@rtc = MYSQL_ERRNO,
@rmg = MESSAGE_TEXT; -- MySQL 5.6 > : comment diagnostics for lower versions
ROLLBACK;
END;
/* table transactions here */
COMMIT;
END tblock; # end: transaction block
SELECT @rtc AS retcode,
@rmg AS retmsg,
'some ret value' AS retval;
END$$
DELIMITER ;
在SQL中,作为标准,0表示成功,非零(通常大于零)表示错误。您可能希望遵循这样的规则并将其作为一种练习。