处理异常错误(运行时错误)
可以使用 PL/SQL 代码处理运行时发生的异常错误。
另请参见: Oracle Database PL/SQL Language Reference(了解有关处理 PL/SQL 错误的详细信息)
关于异常错误和异常错误处理程序
当 PL/SQL 代码中出现运行错误后,将会引发异常错误。如果引发例外的子程序(或块)中具有异常错误处理部分,则控制权限将转到该部分;否则,执行将停止。
运行时的错误可能是由于设计故障、代码错误、硬件故障和许多其他源造成的。
Oracle Database 有许多预定义异常,当程序违反数据库规则或超出系统相关限制时,会自动引发这些异常。例如,如果 SELECT INTO 语句未返回行,则 Oracle Database 会引发预定义的异常错误 NO_DATA_FOUND。有关预定义 PL/SQL 异常的概要说明,请参阅 Oracle Database PL/SQL Language Reference。
可以使用 PL/SQL 定义 (声明) 自己的异常错误。异常错误声明的语法如下:
exception_name EXCEPTION;
与预定义的异常不同,必须使用 RAISE 语句或 DBMS_STANDARD.RAISE_APPLICATION_ERROR. 过程显式引发用户定义的异常。例如:
IF condition THEN RAISE exception_name;
有关 DBMS_STANDARD.RAISE_APPLICATION_ERROR 过程的信息,请参阅 Oracle Database PL/SQL Language Reference。
子程序的异常错误处理部分可以包含一个或多个异常错误处理程序。异常错误处理程序的语法如下:
WHEN { exception_name [ OR exception_name ]... | OTHERS } THEN
statement; [ statement; ]...
(“关于子程序结构”显示将子程序的异常错误处理部分放在何处。)
WHEN OTHERS 异常错误处理程序用于处理意外的运行错误。如果使用,它必须放在最后。例如:
EXCEPTION
WHEN exception_1 THEN
statement; [ statement; ]...
WHEN exception_2 OR exception_3 THEN
statement; [ statement; ]...
WHEN OTHERS THEN
statement; [ statement; ]...
RAISE; -- Reraise the exception (very important).
END;
WHEN OTHERS 异常错误处理程序的替代方法是 EXCEPTION_INIT pragma,它将用户定义的异常错误名称与 Oracle Database 错误编号关联。
另请参见:
-
Oracle Database PL/SQL Language Reference(了解有关异常错误声明语法的详细信息)
-
Oracle Database PL/SQL Language Reference(了解有关异常错误处理程序语法的详细信息)
-
Oracle Database PL/SQL Language Reference(了解有关 EXCEPTION_INIT pragma 的详细信息)
何时使用异常错误处理程序
仅在以下情况下使用异常处理程序。
-
您需要一个异常错误并希望对其进行处理。
例如,您希望最终 SELECT INTO 语句不会返回任何行,从而导致 Oracle Database 引发预定义的异常错误 NO_DATA_FOUND。您希望子程序或块处理该异常错误(这不是错误),然后继续操作,如 Example 5-13 中所示。
-
您必须放弃或关闭资源,如以下示例中所示。
... file := UTL_FILE.OPEN ... BEGIN statement statement]... -- If this code fails for any reason, EXCEPTION WHEN OTHERS THEN UTL_FILE.FCLOSE(file); -- then you want to close the file. RAISE; -- Reraise the exception (very important). END; UTL_FILE.FCLOSE(file); ... -
在代码的顶层,当您想要记录错误时。
例如,客户机进程可能会发出以下块:
BEGIN proc(...); EXCEPTION WHEN OTHERS THEN log_error_using_autonomous_transaction(...); RAISE; -- Reraise the exception (very important). END; /或者,客户机调用的独立子程序可以包含相同的异常处理逻辑,但只能在顶层。
处理预定义异常错误
您可以处理预定义的例外。示例 5-13 显示如何更改 EMP_EVAL.EVAL_DEPARTMENT 过程,以便处理预定义异常错误 NO_DATA_FOUND。请执行此更改并编译更改后的过程。(有关如何更改程序包体的示例,请参阅“教程:在子程序中声明变量和常量”。)
示例 5-13 处理预定义例外 NO_DATA_FOUND
PROCEDURE eval_department(dept_id IN employees.department_id%TYPE) AS
emp_cursor emp_refcursor_type;
current_dept departments.department_id%TYPE;
BEGIN
current_dept := dept_id;
FOR loop_c IN 1..3 LOOP
OPEN emp_cursor FOR
SELECT *
FROM employees
WHERE current_dept = eval_department.dept_id;
DBMS_OUTPUT.PUT_LINE
('Determining necessary evaluations in department #' ||
current_dept);
eval_loop_control(emp_cursor);
DBMS_OUTPUT.PUT_LINE
('Processed ' || emp_cursor%ROWCOUNT || ' records.');
CLOSE emp_cursor;
current_dept := current_dept + 10;
END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE ('The query did not return a result set');
END eval_department;
另请参见: Oracle Database PL/SQL Language Reference(了解有关预定义异常错误的详细信息)
声明和处理用户定义的异常错误
您可以声明和处理用户定义的异常错误。示例 5-14 显示如何更改 EMP_EVAL.CALCULATE_SCORE 函数,以便声明和处理两个用户定义的异常错误 wrong_weight 和 wrong_score。请执行此更改并编译更改后的函数。(有关如何更改程序包体的示例,请参阅“教程:在子程序中声明变量和常量”。)
示例 5-14 处理用户定义的异常错误
FUNCTION calculate_score ( evaluation_id IN scores.evaluation_id%TYPE
, performance_id IN scores.performance_id%TYPE )
RETURN NUMBER AS
weight_wrong EXCEPTION;
score_wrong EXCEPTION;
n_score scores.score%TYPE;
n_weight performance_parts.weight%TYPE;
running_total NUMBER := 0;
max_score CONSTANT scores.score%TYPE := 9;
max_weight CONSTANT performance_parts.weight%TYPE:= 1;
BEGIN
SELECT s.score INTO n_score
FROM SCORES s
WHERE evaluation_id = s.evaluation_id
AND performance_id = s.performance_id;
SELECT p.weight INTO n_weight
FROM PERFORMANCE_PARTS p
WHERE performance_id = p.performance_id;
BEGIN
IF (n_weight > max_weight) OR (n_weight < 0) THEN
RAISE weight_wrong;
END IF;
END;
BEGIN
IF (n_score > max_score) OR (n_score < 0) THEN
RAISE score_wrong;
END IF;
END;
running_total := n_score * n_weight;
RETURN running_total;
EXCEPTION
WHEN weight_wrong THEN
DBMS_OUTPUT.PUT_LINE(
'The weight of a score must be between 0 and ' || max_weight);
RETURN -1;
WHEN score_wrong THEN
DBMS_OUTPUT.PUT_LINE(
'The score must be between 0 and ' || max_score);
RETURN -1;
END calculate_score;
另请参见: Oracle Database PL/SQL Language Reference(了解有关用户定义异常错误的详细信息)