MySQL存储过程错误处理

13

据我所知,目前在MySQL中没有任何可用的方法来访问MySQL存储过程中最后一个执行语句的SQLSTATE。这意味着,当存储过程中引发通用的SQLException时,很难/不可能确定错误的确切性质。

有没有人有一种方法可以推导出MySQL存储过程中错误的SQLSTATE,而不涉及为每个可能的SQLSTATE声明处理程序的解决方法?

例如-假设我正在尝试在以下代码块中返回超出常规“SQLException发生在此BEGIN....END块中某处”的错误状态:

DELIMITER $$

CREATE PROCEDURE `myProcedure`(OUT o_error_status varchar(50))
MY_BLOCK: BEGIN

 DECLARE EXIT handler for 1062 set o_error_status := "Duplicate entry in table";
 DECLARE EXIT handler for 1048 set o_error_status := "Trying to populate a non-null column with null value"; 
-- declare handlers ad nauseum here....

 DECLARE EXIT handler for sqlexception set o_error_status:= "Generic SQLException. You'll just have to figure out the SQLSTATE yourself...." ;

-- Procedure logic that might error to follow here...

END MY_BLOCK$$

有什么建议吗?

PS,我正在运行MySQL 5.1.49

3个回答

11

我认为MySQL中目前没有任何可以访问MySQL存储过程内最后一个执行语句的SQLSTATE的东西。这意味着... 很难/不可能推导出错误的确切性质。

幸运的是这是不正确的。

SHOW ERRORS LIMIT 1   -- for SQL-state > 2
SHOW WARNINGS LIMIT 1 -- for SQL-state 1,2
展示最后一个错误或警告。
为了避免列出每一个错误,您可以这样处理 SQL 错误的分类:
SQLWARNING 是 SQLSTATE 值以“01”开头的类别的简写。
NOT FOUND 是 SQLSTATE 值以“02”开头的类别的简写。这仅适用于游标内部,用于控制当游标到达数据集的末尾时发生的情况。如果没有更多的行可用,则会出现 No Data 状态,其 SQLSTATE 值为 02000。要检测此条件,可以设置处理程序(或 NOT FOUND 条件)。Section 12.7.5,“Cursors” 显示了一个示例。对于检索不到行的 SELECT ... INTO var_list 语句也会出现此条件。
SQLEXCEPTION 是 SQLSTATE 值不以“00”、“01”或“02”开头的类别的简写。
因此,要处理异常,您只需要执行以下操作:
DECLARE EXIT HANDLER FOR SQLSTATE SQLEXCEPTION .....;

链接:
http://dev.mysql.com/doc/refman/5.5/en/signal.html
http://dev.mysql.com/doc/refman/5.0/en/declare-handler.html


2
谢谢Johan。如果单独运行,“SHOW ERRORS”和“SHOW WARNINGS”确实会显示最后一个错误或警告的SQLSTATE。但是,我如何在MySQL存储过程中访问它们?也就是说,我如何将“SHOW ERRORS”或“SHOW WARNINGS”的输出作为过程输出变量返回,就像我原来的问题描述的那样? - Tom Mac
1
如何将 SHOW ERRORS 的结果存储到一个变量中? - AAEM

10

1
谢谢!非常有用。现在我只需要升级到5.6版本了;-) - Tom Mac

0
我正在进行以下解决方法:使用SELECT来引发错误。例如:
SELECT RAISE_ERROR_unable_to_update_basket;

这将导致以下错误消息(示例):

ERROR 1054 (42S22): Unknown column 'RAISE_ERROR_unable_to_update_basket' in 'field list'

我将对存储过程的调用进行try { ... } catch { ... }包装,现在可以处理这个错误。当然,这只适用于从存储过程内部引发自定义错误消息,并且不会处理可能发生的任何SQL或数据库错误(因为重复键入条目)。在后一种情况下,您可能可以使用Johan的解决方案来解决此问题。


谢谢Harald。在这个特定情况下,我正在尝试处理SQL或数据库错误。 - Tom Mac

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接