一、异常类型
本文讨论用户定义的错误。
二、捕获用户定义的异常
PL / SQL允许你定义你自己的异常。 您根据应用程序的要求定义异常。
输入数据期间需要用户定义的异常的一个示例。 假设您的程序提示用户输入部门编号和名称,以便它可以更新部门的名称。 当用户进入无效部门时会发生什么? 该代码不会产生Oracle错误。 你需要定义一个预定义的用户错误来引发错误。
DECLAREv_name VARCHAR2(20):='Accounting';v_deptno NUMBER := 27;
BEGINUPDATE departmentsSET department_name = v_nameWHERE department_id = v_deptno;
END;
当用户进入无效部门时会发生什么?
编写的代码不会产生Oracle错误。 需要定义一个预定义的用户错误来引发错误。
可以这样做:
1.在声明部分声明用户定义的异常的名称。e_invalid_department EXCEPTION;
2.使用RAISE语句在可执行部分中明确地引发异常。
IF SQL%NOTFOUND THEN RAISE e_invalid_department;
3.在相应的异常处理例程中引用声明的异常。
EXCEPTIONWHEN e_invalid_department THENDBMS_OUTPUT.PUT_LINE('No such department id.');
以下是完整的代码。
1.在声明部分中声明用户定义的异常的名称。 语法:exception EXCEPTION; exception是异常的名称。
2.使用RAISE语句在可执行部分中显式引发异常。 语法:RAISE exception; 其中exception是先前声明的异常。
3.在相应的异常处理例程中引用已声明的异常。
三、RAISE声明
可以使用RAISE语句来引发一个指定的异常。 你可以提出:
•自己的异常(即用户定义的异常)
IF v_grand_total=0 THENRAISE e_invalid_total;
ELSE
DBMS_OUTPUT.PUT_LINE(v_num_students/v_grand_total);
END IF;
•Oracle服务器错误
IF v_grand_total=0 THENRAISE ZERO_DIVIDE;
ELSEDBMS_OUTPUT.PUT_LINE(v_num_students/v_grand_total);
END IF;
四、RAISE_APPLICATION_ERROR过程
可以使用RAISE_APPLICATION_ERROR过程从存储的子程序返回用户定义的错误消息。使用RAISE_APPLICATION_ERROR而不是RAISE的主要优点是RAISE_APPLICATION_ERROR允许您将自己的错误号和有意义的消息与异常关联。
错误编号必须介于-20000和-20999之间。
(1)语法:
RAISE_APPLICATION_ERROR (error_number, message[, {TRUE | FALSE}]);
•error_number是-20000和-20999之间的异常的用户指定编号
•消息是异常的用户指定消息。 它是一个长达2048字节的字符串。
•TRUE | FALSE是一个可选的布尔参数。
(如果为TRUE,则将错误放置在之前错误的堆栈上。如果FALSE-默认 - 错误将替换以前的所有错误。)
数字范围-20000到-20999由Oracle保留供程序员使用,并且从不用于预定义的Oracle Server错误。
(2)可以在两个不同的地方使用RAISE_APPLICATION_ERROR:
•可执行部分
•异常部分
(3)可执行部分中的RAISE_APPLICATION_ERROR
被调用时,RAISE_APPLICATION_ERROR过程向用户显示错误号和消息。 此过程与其他Oracle服务器错误一致。
DECLAREv_mgr PLS_INTEGER := 123;
BEGINDELETE FROM employeesWHERE manager_id = v_mgr;IF SQL%NOTFOUND THENRAISE_APPLICATION_ERROR(-20202, 'This is not a valid manager');END IF;
END;
(4)异常部分中的RAISE_APPLICATION_ERROR
DECLAREv_mgr PLS_INTEGER := 27;v_employee_id employees.employee_id%TYPE;
BEGINSELECT employee_id into v_employee_idFROM employeesWHERE manager_id = v_mgr;DBMS_OUTPUT.PUT_LINE('The employee who works for manager_id '||v_mgr||' is: '||v_employee_id);
EXCEPTIONWHEN NO_DATA_FOUND THENRAISE_APPLICATION_ERROR (-20201, 'This manager has no employees');WHEN TOO_MANY_ROWS THENRAISE_APPLICATION_ERROR (-20202,'Too many employees were found.');
END;
(5)将RAISE_APPLICATION_ERROR与用户定义的异常一起使用
DECLAREe_name EXCEPTION;PRAGMA EXCEPTION_INIT (e_name, -20999);v_last_name employees.last_name%TYPE := 'Silly Name';
BEGINDELETE FROM employees WHERE last_name = v_last_name;IF SQL%ROWCOUNT =0 THENRAISE_APPLICATION_ERROR(-20999,'Invalid last name');ELSEDBMS_OUTPUT.PUT_LINE(v_last_name||' deleted');END IF;
EXCEPTION WHEN e_name THENDBMS_OUTPUT.PUT_LINE ('Valid last names are: ');FOR c1 IN (SELECT DISTINCT last_name FROM employees)LOOPDBMS_OUTPUT.PUT_LINE(c1.last_name);END LOOP;WHEN OTHERS THENDBMS_OUTPUT.PUT_LINE('Error deleting from employees');
END;