Oracle PL/SQL开发基础(第三十六弹:异常处理的一些经验)

从异常中恢复

当触发异常以后,代码的执行立即跳转到异常处理部分,异常处理部分结束后,语句块就终止了。如果在处理完异常之后想继续执行抛出异常的地方后面的代码,可以将异常包装在子块中,在子块中写对应的异常控制程序,这样一旦在子块中有错误发生,子块内部的异常处理器就捕获异常。当子块结束时,就可以继续执行外层块中的下一条语句。

获取异常抛出的位置

如下代码:

DECLARE
    ...
BEGIN 
    SELECT sal INTO v_sal1 FROM emp WHERE empno = '1';
    SELECT sal INTO v_sal2 FROM emp WHERE empno = '2';
    SELECT sal INTO v_sal3 FROM emp WHERE empno = '3';
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        ...
END;

当触发了NO_DATA_FOUND异常时,怎么知道是哪个SELECT语句触发了异常呢?

方法一:使用计数器

如:

DECLARE
    v_count NUMBER := 1;
BEGIN 
    SELECT sal INTO v_sal1 FROM emp WHERE empno = '1';
    v_count  := 2;
    SELECT sal INTO v_sal2 FROM emp WHERE empno = '2';
    v_count  := 3;
    SELECT sal INTO v_sal3 FROM emp WHERE empno = '3';
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        ...
END;

触发异常时,根据计数器就能跟踪到时哪个语句触发了异常。

方法二:使用子块

将每一个SELECT语句分别定义到一个子块中,每个子块中都可以捕获异常。如:

DECLARE
    ...
BEGIN 
    BEGIN
        SELECT sal INTO v_sal1 FROM emp WHERE empno = '1';
    EXCEPTION
        WHEN NO_DATA_FOUND THEN
            ...
    END;
    BEGIN
        SELECT sal INTO v_sal2 FROM emp WHERE empno = '2';
    EXCEPTION
        WHEN NO_DATA_FOUND THEN
            ...
    END;
    BEGIN
        SELECT sal INTO v_sal3 FROM emp WHERE empno = '3';
    EXCEPTION
        WHEN NO_DATA_FOUND THEN
            ...
    END;
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        ...
END;

方法三:使用DBMS_UTILITY.FORMAT_ERROR_BACK_TRACE函数

这个函数是Oracle 10g以后的版本提供的。在异常处理程序中调用这个函数来访问异常的栈,它可以返回错误发生的行号。

异常与事务处理

抛出一个异常并不会终止一个事务,除非显式的调用了ROLLBACK或COMMIT。但是这里有一个问题,如果顶层的语句块存在一个未处理的异常,该异常将被传递到调用环境,那么事务将被服务器端自动回滚。
如果想在异常发生后,不放弃事务,不进行回滚,重新再处理一次,可以按如下三步来实现:
1. 将事务放在一个子块中。
2. 把子块放入一个循环,重复执行事务。
3. 在开始事务之前标记一个保存点,如果事务执行成功,就提交事务并退出循环,如果执行失败,就将控制权交给异常处理程序,事务回滚到保存点,然后重新执行事务。

如:

BEGIN
    LOOP
        BEGIN
            SAVEPOINT 开始事务;
            ...
            IF ... THEN
                RAISE e_some_exception;
            END IF;
            ...
            COMMIT;
            EXIT;
        EXCEPTION
            WHEN e_some_exception THEN
                ROLLBACK TO 开始事务;
                ...  -- 这里可以为一些变量重新赋值等等,重新开始循环执行。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值