暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Halo数据库兼容MySQL存储过程之异常

Halo Tech 2025-05-13
130

引言

    众所周知,在高级编程语言中,可以在可能出错的代码外围添加类似try ... catch的方法捕获异常,用户可以添加自己想要的异常处理逻辑,从而保证系统的稳定运行。在各个数据库中,同样存在类似的功能,该功能用于存储过程中,可以保证存储过程的稳定运行,从而增强系统的健壮性。

    羲和(Halo)数据库从语法和功能两方面全面兼容MySQL数据库的异常处理功能,用户无需修改使用MySQL语法编写的异常处理代码,可直接在Halo数据库中进行创建及使用。

MySQL异常处理语法说明

    在MySQL存储过程中,使用异常处理的语法如下:

    DECLARE handler_action HANDLER
    FOR condition_value [, condition_value] ...
    statement
    handler_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(
      char(1),
      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()
        begin
            declare continue handler for sqlexception
                begin
                    select "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()
            begin
                declare continue handler for sqlexception
                    begin
                        select "execute outer continue handler" as msg;
                    end;


                begin
                    insert 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()
                begin
                    declare exit handler for sqlexception
                        begin
                            select "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()
                    begin
                        declare exit handler for sqlexception
                            begin
                                select "execute outer exit handler" as msg;
                            end;


                        begin
                            insert 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)数据库将会越来越好。

                      文章转载自Halo Tech,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                      评论