没有一种合适的方式来捕捉和诊断 MySQL 服务器端的错误,因此想知道什么地方出错了基本上是不可能的。
我们使用下面这样一个查询来证明这个结论:
| 1
 
 | INSERTINTOmy_table (my_column) VALUES(300);
 | 
这个查询可能发生什么错误?
- 违反 UNIQUE KEY 约束
 
 
- 违反 FOREIGN KEY 约束
 
 
- my_column 字段类型可能是 TINYINT UNSIGNED, 而严格的 sql_mode 导致数值越界
 
 
- 后者字段类型可能是某个枚举,如 ENUM (2,3,5,8)
 
 
还有可能是这样一些错误:
- my_table 可能是一个只读的 MyISAM 表
 
 
- 我们对 my_table 进行了锁表操作 LOCK TABLES my_table READ -- 违反了锁
 
 
- 或者可能是一个 InnoDB 表,而 INSERT 可能导致死锁
 
 
- 配置了 read_only=1 只读
 
 
- 或者用户没法访问该表的权限
 
 
- 或者表不存在
 
 
- 也有可能是字段不存在
 
 
而且我还确定还可能有更多的错误原因存在。
现在,如果我写了一个 Java 程序,可能用了 Hibernate,那么我将会通过 SQLException 得到一个描述比较清晰的异常信息,我可以得知错误码和错误信息。
但在 MySQL 的服务器端,例如是存储过程呢?则不行!
再看看下面的代码:
| 1
 
 2
 
 3
 
 4
 
 5
 
 6
 
 | CREATEPROCEDUREsome_procedure ()
 
 BEGIN
 
 DECLARECONTINUEHANDLER FORSQLEXCEPTION SET@error_found = 1;
 
 INSERTINTOmy_table (my_column) VALUES(300);
 
 IF @error_found THEN-- Any what error exactly is this? What's the message? END IF;
 
 END;
 | 
如果我们希望为指定的错误执行相应的动作,我们需要:
| 1
 
 2
 
 3
 
 4
 
 5
 
 | DECLARECONTINUEHANDLER FOR1146 SET@error_found = 1146;
 
 DECLARECONTINUEHANDLER FOR1147 SET@error_found = 1147;
 
 DECLARECONTINUEHANDLER FOR1148 SET@error_found = 1148;
 
 DECLARECONTINUEHANDLER FOR1149 SET@error_found = 1149;
 
 ...
 | 
但如果我们比知道将会发生什么错误,但仍希望记录这个错误,这样我们可能需要定义成百上千的 HANDLERs,尽管如此还是无法覆盖所有的错误情况。
5.5 版本不是引入了 SINGAL 和 RESIGNAL 了吗?
是的,的确是引入了,但对你毫无帮助,你可以重新 RESIGNAL 一个错误,但并不意味着错误实际发生时你能知晓。