一、异常类型
本课讨论预定义和非预定义的Oracle服务器异常。
(1)使用PL / SQL处理异常
有两种提出异常的方法:•Oracle服务器隐式(自动):
- 发生Oracle错误并自动引发相关异常。
- 例如,如果在SELECT语句中没有从数据库中检索行时发生错误ORA-01403,则PL / SQL引发异常NO_DATA_FOUND。
•程序员明确指出:
- 根据您的程序正在执行的业务功能,您可能必须明确提出异常。
- 通过在块内发出RAISE语句显式引发异常。
- 引发的异常可以是用户定义的或预定义的。 这些在下一课中解释。
(2)两种类型的Oracle服务器错误
当发生Oracle服务器错误时,Oracle服务器会自动引发关联的异常,跳过块的可执行部分的其余部分,并在异常部分查找处理程序。
有两种类型的Oracle服务器错误:
•预定义的Oracle服务器错误:
- 每个错误都有一个预定义的名称。
- 例如,如果在SELECT语句中没有从数据库中检索到行时发生错误ORA-01403,则PL / SQL会引发预定义的异常名称NO_DATA_FOUND。
•非预定义的Oracle服务器错误:
- 这些错误中的每一个都有一个标准的Oracle错误编号(ORA-nnnnn)和错误消息,但不是预定义的名称。
- 为这些名称声明自己的名称,以便可以在异常部分中引用这些名称。
(3)捕获预定义的Oracle服务器错误
在异常处理例程中引用预定义的名称。•预定义例外示例:
- NO_DATA_FOUND
- TOO_MANY_ROWS
- INVALID_CURSOR
- ZERO_DIVIDE
- DUP_VAL_ON_INDEX
有关预定义例外的部分列表,请参阅第0部分中的学生资源中提供的简短列表。
有关预定义例外的完整列表,请参阅PL / SQL用户指南和参考。
以下示例使用TOO_MANY_ROWS预定义的Oracle服务器错误。 请注意,它未在声明部分中声明。
DECLARE
v_lname VARCHAR2(15);
BEGIN
SELECT last_name INTO v_lname
FROM employees WHERE job_id = 'ST_CLERK';
DBMS_OUTPUT.PUT_LINE('The last name of the ST_CLERK is: '||v_lname);
EXCEPTION
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE (' Your select statement retrieved multiple
rows. Consider using a cursor.');
END;
此示例处理TOO_MANY_ROWS和NO_DATA_FOUND,并在出现任何其他错误时使用OTHERS处理程序。
DECLARE
v_lname VARCHAR2(15);
BEGIN
SELECT last_name INTO v_lname
FROM employees WHERE job_id = 'ST_CLERK';
DBMS_OUTPUT.PUT_LINE('The last name of the ST_CLERK is: '||v_lname);
EXCEPTION
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE ('Select statement found multiple rows');
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE ('Select statement found no rows');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE ('Another type of error occurred');
END;
捕获非预定义的Oracle服务器错误非预定义的例外与预定义的例外类似; 但是,它们在PL / SQL中没有预定义的名称。 它们是标准的Oracle服务器错误,并具有ORA错误编号。
可以在DECLARE部分为他们创建自己的名称,并使用PRAGMA EXCEPTION_INIT函数将这些名称与ORA-错误号相关联。
•可以通过首先声明它来捕获非预定义的Oracle服务器错误。 声明的异常是隐含提出的。 在PL / SQL中,PRAGMA EXCEPTION_INIT指示编译器将异常名称与Oracle错误号关联。
•这允许通过名称引用任何Oracle Server异常并为其编写特定的处理程序。
二、非预定义错误
检查以下示例。
BEGIN
INSERT INTO departments
(department_id, department_name) VALUES (280, NULL);
END;
ORA-01400: cannot insert NULL into (“USVA_TEST_SQL01_S01”.“DEPARTMENTS”. “DEPARTMENT_NAME”)
INSERT语句尝试插入department表的department_name列的值NULL。但是,操作不成功,因为department_name是NOT NULL列。 没有违反NOT NULL约束的预定义错误名称。解决此问题的方法是声明您自己的名称并将其与ORA-01400错误关联。
1.在声明部分声明异常的名称。
2.使用PRAGMA EXCEPTION_INIT函数将声明的异常与标准Oracle服务器错误号相关联。
3.在相应的异常处理例程中引用声明的异常名称。
三、捕获异常的函数
发生异常时,可以使用两个函数检索相关的错误代码或错误消息。根据代码或消息的值,您可以决定采取哪些后续操作。
•SQLERRM返回包含与错误编号关联的消息的字符数据。
•SQLCODE返回错误代码的数字值。 (您可以将其分配给NUMBER变量。)
不能在SQL语句中直接使用SQLCODE或SQLERRM。 相反,您必须将它们的值分配给本地变量,然后使用SQL语句中的变量,如以下示例中所示:
DECLARE
v_error_code NUMBER;
v_error_message VARCHAR2(255);
BEGIN
...
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
v_error_code := SQLCODE ;
v_error_message := SQLERRM ;
INSERT INTO error_log(e_user,e_date,error_code,error_message)
VALUES(USER,SYSDATE,v_error_code,v_error_message);
END;