您的位置:首页 > 数据库 > Oracle

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

2016-12-18 10:53 399 查看

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子句,中间放你想捕获的异常名字。异常抛出时,会执行对应异常处理程序中包含的语句。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  oracle 异常