Oracle异常 创建并抛出命名的自定义异常

9.3 创建并抛出命名的自定义异常

问题

你想在某个特定事件发生时向应用程序的用户发出一些警告信息。事件本身不会抛出Oracle内部异常,因为这个异常是属于应用程序的特定异常。所以,你需要把这个事件与自定义异常关联起来,这样一来,不论事件在什么时候发生异常都可以抛出。

解决方案

声明一个用户定义的命名异常,并把它与你想抛出的异常事件相关联。下面的例子在代码块中声明并抛出一个用户定义的异常。异常抛出时,应用程序的控制权就会传递给控制用户命名异常的异常处理程序。

CREATE OR REPLACE PROCEDURE salary_increase(emp_id IN NUMBER,
                                            pct_increase IN NUMBER) AS

  salary                employees.salary%TYPE;
  max_salary            jobs.max_salary%TYPE;
  INVALID_INCREASE      EXCEPTION;


BEGIN

  SELECT salary, max_salary
  INTO salary, max_salary
  FROM employees, jobs
  WHERE employee_id = emp_id
  AND jobs.job_id = employees.employee_id;


  IF (salary + (salary * pct_increase)) <= max_salary THEN
    UPDATE employees
    SET salary = (salary + (salary * pct_increase))
    WHERE employee_id = emp_id;

    DBMS_OUTPUT.PUT_LINE('SUCCESSFUL SALARY INCREASE FOR EMPLOYEE #: ' ||
          emp_id ||
          '.  NEW SALARY = ' || salary + (salary * pct_increase));

  ELSE
    RAISE INVALID_INCREASE;
  END IF;



EXCEPTION
  WHEN NO_DATA_FOUND THEN
    DBMS_OUTPUT.PUT_LINE('UNSUCCESSFUL INCREASE, NO EMPLOYEE RECORD FOUND ' ||
                  'FOR THE GIVEN ID');

  WHEN INVALID_INCREASE THEN
    DBMS_OUTPUT.PUT_LINE('UNSUCCESSFUL INCREASE.  YOU CANNOT INCREASE THE ' ||
                  'EMPLOYEE SALARY BY ' || pct_increase ||
                  'PERCENT...PLEASE ENTER ' ||
                  'A SMALLER INCREASE AMOUNT TO TRY AGAIN');


  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE('UNSUCCESSFUL INCREASE.  AN UNCKNOWN ERROR HAS '||
                  'OCCURRED, ' ||
                  'PLEASE TRY AGAIN OR CONTACT ADMINISTRATOR' || pct_increase);

END;
/

从代码中可以看出,异常块可以容纳一个或多个处理程序。命名的用户异常在过程的声明部分声明,并且这个异常可以在代码块的任何地方抛出。

注意 在真实的应用程序中,异常应该在OTHERS处理程序中手动引发。关于如何确定异常起因的更多内容请参考9.4节。

原理分析

一个PL/SQL应用程序可以包含任意数量的自定义异常。开发人员声明了他们自己的异常时,这些异常就称为用户定义异常。用户定义异常必须在包、函数、过程或匿名代码块的声明部分声明。要声明一个异常,可以使用下面的语法:
exception_name EXCEPTION;
对于异常的命名,只要符合标准的命名规范并且不同于内部定义的异常名称,都可以使用。规范的异常名称应该全部采用大写,但小写也可以使用,因为PL/SQL语言不区分大小写。
如果想抛出你自己的异常,需要在RAISE关键字后面加上你要抛出的异常名称。代码执行到RAISE语句时,控制权就会传递给与命名异常最为匹配的异常处理程序。如果找不到与抛出异常相匹配的异常处理程序,控制权就会传入OTHERS处理程序,但前提是存在OTHERS处理程序。而在最糟糕的情况下,如果没有任何异常处理程序能够与RAISE语句中抛出的异常名称相匹配,并且代码中也没有编写OTHERS处理程序,控制权就会被传回外层代码块、调用当前程序的代码块或是宿主环境。
关于RAISE语句,除了上面提到的一种用法之外,还有别的用法。比如抛出一个在其他包中声明的异常。为此,需要在异常的前面加上完整的包名作为前缀。另外,RAISE语句也可以独立使用,用来重新抛出一个异常。
从这个案例的解决方案中可以看出,捕获命名的用户异常与捕获内部定义异常完全一样。都是编写一个WHEN…THEN子句,中间放你想捕获的异常名字。异常抛出时,会执行对应异常处理程序中包含的语句。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值