引言
众所周知,在高级编程语言中,可以在可能出错的代码外围添加类似try ... catch的方法捕获异常,用户可以添加自己想要的异常处理逻辑,从而保证系统的稳定运行。在各个数据库中,同样存在类似的功能,该功能用于存储过程中,可以保证存储过程的稳定运行,从而增强系统的健壮性。
羲和(Halo)数据库从语法和功能两方面全面兼容MySQL数据库的异常处理功能,用户无需修改使用MySQL语法编写的异常处理代码,可直接在Halo数据库中进行创建及使用。
MySQL异常处理语法说明
在MySQL存储过程中,使用异常处理的语法如下:
DECLARE handler_action HANDLERFOR condition_value [, condition_value] ...statementhandler_action: {CONTINUE| EXIT| UNDO}condition_value: {mysql_error_code| SQLSTATE [VALUE] sqlstate_value| condition_name| SQLWARNING| NOT FOUND| SQLEXCEPTION}
上述语法可以为一种或多种异常条件确定一种异常处理方式,当这些异常条件中的某个异常条件发生时,指定的statement将被执行,statement可以是一个简单的SQL语句,也可以是一个begin ... end复合语句块。
handler_action表示在异常发生,statement执行之后存储过程将要采取的动作,CONTINUE表示继续执行后续逻辑,EXIT表示退出声明该异常处理的begin ... end复合语句块,UNDO尚未实现。
condition_value表示异常条件。
羲和(Halo)数据库兼容MySQL存储过程异常处理说明
1.兼容MySQL异常处理语法(declare ... handler)。
2.兼容MySQL异常处理语法中handler_action的CONTINUE, EXIT值。
3.兼容MySQL异常处理语法中condition_value的NOT FOUND,SQLEXCEPTION值。
羲和(Halo)数据库兼容MySQL存储过程异常处理测试
1.创建测试表t3并准备数据
create table t3(w char(1),x char(1),unique key(w));insert into t3 values('a', 'b');

2.handler_action取值为CONTINUE时的测试
情况1:在可能发生异常的同级begin ... end块中声明异常处理逻辑
创建测试存储过程ptest_t3:
delimiter //create procedure ptest_t3()begindeclare continue handler for sqlexceptionbeginselect "execute ptest_t3 continue handler" as msg;end;insert into t3 values('a', 'c');insert into t3 values('b', 'c');end//delimiter ;

在测试存储过程ptest_t3中,声明了handler_action取值为CONTINUE的异常处理逻辑。因为测试表t3的w字段上有唯一索引,且表中w字段已有’a’值,当调用ptest_t3时,执行第一条insert语句会触发异常,从而执行异常处理逻辑,输出描述信息,至此,第一条insert处理完成。因为该异常的handler_action取值为CONTINUE,之后会继续执行第二条insert语句,该语句插入的值不会违反唯一键约束,不会触发异常,数据正常插入到测试表t3中。
测试存储过程ptest_t3调用及结果如下:
call ptest_t3();select * from t3;

情况2:在可能发生异常的begin ... end块的外层声明异常处理逻辑
删除表t3中的新增数据,重新创建测试存储过程ptest_t3:
delete from t3 where w='b';drop procedure if exists ptest_t3;delimiter //create procedure ptest_t3()begindeclare continue handler for sqlexceptionbeginselect "execute outer continue handler" as msg;end;begininsert into t3 values('a', 'c');insert into t3 values('b', 'c');end;insert into t3 values('b', 'd');end//delimiter ;

在测试存储过程ptest_t3的外层begin ... end块中声明了handler_action取值为CONTINUE的异常处理逻辑。因为测试表t3的w字段上有唯一索引,且表中w字段已有’a’值,当调用ptest_t3时,执行内层begin ... end块中第一条insert语句会违反唯一键约束触发异常,从而执行外层begin ... end块异常处理逻辑,输出描述信息,至此,第一条insert处理完成。因为该异常的handler_action取值为CONTINUE,之后会继续执行内层begin ... end块的第二条insert语句,该语句插入的值不会违反唯一键约束,不会触发异常,数据正常插入到测试表t3中,至此,第二条insert处理完成,内层begin ... end块执行完成。之后继续执行外层begin ... end块下的insert语句,这条语句插入的数据会违反唯一键约束触发异常,从而又执行外层begin ... end块异常处理逻辑,输出描述信息。
测试存储过程ptest_t3调用及结果如下:
call ptest_t3();select * from t3;

3.handler_action取值为EXIT时的测试
情况1:在可能发生异常的同级begin ... end块中声明异常处理逻辑
删除表t3中的新增数据,重新创建测试存储过程ptest_t3:
delete from t3 where w='b';drop procedure if exists ptest_t3;delimiter //create procedure ptest_t3()begindeclare exit handler for sqlexceptionbeginselect "execute ptest_t3 exit handler" as msg;end;insert into t3 values('a', 'c');insert into t3 values('b', 'c');end//delimiter ;

在测试存储过程ptest_t3中,声明了handler_action取值为EXIT的异常处理逻辑。因为测试表t3的w字段上有唯一索引,且表中w字段已有’a’值,当调用ptest_t3时,执行第一条insert语句会触发异常,从而执行异常处理逻辑,输出描述信息,至此,第一条insert处理完成。因为该异常的handler_action取值为EXIT,之后会直接退出声明该异常处理的begin ... end块,不会执行第二条insert语句,所以测试表t3不会有新数据。
测试存储过程ptest_t3调用及结果如下:
call ptest_t3();select * from t3;

情况2:在可能发生异常的begin ... end块的外层声明异常处理逻辑
重新创建测试存储过程ptest_t3:
drop procedure if exists ptest_t3;delimiter //create procedure ptest_t3()begindeclare exit handler for sqlexceptionbeginselect "execute outer exit handler" as msg;end;begininsert into t3 values('a', 'c');insert into t3 values('b', 'c');end;insert into t3 values('b', 'd');end//delimiter ;

在测试存储过程ptest_t3的外层begin ... end块中声明了handler_action取值为EXIT的异常处理逻辑。因为测试表t3的w字段上有唯一索引,且表中w字段已有’a’值,当调用ptest_t3时,执行内层begin ... end块中第一条insert语句会违反唯一键约束触发异常,从而执行外层begin ... end块异常处理逻辑,输出描述信息,至此,第一条insert处理完成。因为该异常的handler_action取值为EXIT,所以直接从外层begin ... end块退出,存储过程调用完毕。
测试存储过程ptest_t3调用及结果如下:
call ptest_t3();select * from t3;

小结
我们从不同客户的迁移案例中总结经验,并对羲和(Halo)数据库兼容MySQL的功能进行了大量测试,羲和(Halo)数据库对于MySQL有着很强的兼容性。在未来,我们将虚心接受大家提出的问题,经过不断的技术迭代,我们相信羲和(Halo)数据库将会越来越好。




