一、异常的种类
plsql中有三种异常:用户自定义异常(Predefined):程序员自己定义而非oracle公司自己预先定以的一个错误,往往和用户自己的特定业务常见或业务逻辑有关。需要用户在程序中显式的定义错误描述,并由用户自己触发。
预定义异常:由oracle公司预先定义好的,同时具有错误编码(ORA-XXXXX)和错误描述的常见SQL和PL/SQL错误。大约有24个。由SQL自动定义并触发(在条件被满足的时候)。
非预定义异常:有oracle公司预先定义好错误编码(ORA-XXXXX),但是没有错误描述(需要用户在程序中自己定义)的常见SQL和PL/SQL错误。由用户在程序中显示定义,但由SQL自动触发(在条件被满足的时候)。
二、异常的触发和捕获。
1、对异常捕获:
异常在下面的代码块中被捕获:BEGIN
--some sql scripts
EXCEPTION
WHEN 1ST_ERROR_DESC THEN
--some sql scripts for handle the exception
WHEN 2ND_ERROR_DESC THEN
--some sql scripts for handle the exception
WHEN OTHERS THEN
--catch all the other errors and handle them here
END;
其中,1ST_ERROR_DESC/2ND_ERROR_DESC代表错误描述(包括预定义的,或非预定义的,或用户自定义的),OTHERS 是oracle预定义的,代表所有没有在前面被捕获的异常。
2、对异常的定义
对预定义异常,由于它已经由oracle定义好了其错误编码和错误描述,因此可以直接使用,无需我们再进行定义。
而非预定义异常,oracle只定义了其错误编码,但没有定义错误描述;因此在使用前,必须先定义一个错误描述,然后使用PRAGMA EXCEPTION_INIT(ERROR_NAME, ORACLE_ERROR_COD)语句,将错误描述和错误编码绑定起来,之后才能使用。
对用户自定义的异常,由于是由用户自己触发的,因此没有错误编码,只需要定义错误描述即可。
定义错误描述的语句:ERROR_NAME EXCEPTION;其中,ERROR_NAME就是你定义的错误描述字符串;
绑定错误描述和错误码的语句:PRAGMA EXCEPTION_INIT(ERROR_NAME, ORACLE_ERROR_CODE);其中,ERROR_NAME为错误描述,而ORACLE_ERROR_CODE为oracle预定义的错误编码。
3、捕获各类异常的例子
DECLARE
-- 用户自定义了一个异常类别
e_DuplicateAuthors EXCEPTION;
--用户将oracle错误码 ORA-01400 定义为 e_MissingNull
e_MissingNull EXCEPTION;
PRAGMA EXCEPTION_INIT(e_MissingNull, -1400);
-- IDs for three authors
v_Author1 books.author1%TYPE;
v_Author2 books.author2%TYPE;
v_Author3 books.author3%TYPE;
-- Code and text of other runtime errors
v_ErrorCode log_table.code%TYPE;
v_ErrorText log_table.message%TYPE;
BEGIN
-- Find the IDs for the 3 authors of 'Oracle9i DBA 101'
SELECT author1, author2, author3
INTO v_Author1, v_Author2, v_Author3
FROM books
WHERE title = 'Oracle9i DBA 101';
-- Ensure that there are no duplicates
IF (v_Author1 = v_Author2) OR (v_Author1 = v_Author3) OR (v_Author2 = v_Author3) THEN
--抛出一个用户自定义异常
RAISE e_DuplicateAuthors;
END IF;
EXCEPTION
--捕获用户自定义异常,跟捕获预定义异常的方式完全一样
WHEN e_DuplicateAuthors THEN
-- 当异常被触发时,对异常进行处理的语句;其实就是普通的sql或plsql语句。
INSERT INTO log_table (info) VALUES ('Oracle9i DBA 101 has duplicate authors');
--捕获预定义异常,它在条件被满足时由sql自动触发(比如没有找到title为'Oracle9i DBA 101'的书籍时)
WHEN NO_DATA_FOUND THEN
v_Author1 := '';
v_Author2 := '';
v_Author3 := '';
--捕获预定义异常,它在条件被满足时由sql自动触发(比如没有找到title为'Oracle9i DBA 101'的书籍时)
WHEN e_MissingNull THEN
dbms_output.put_line('missing some null value');
-- 发生其他任何异常时,进行处理。OTHERS必须是最后一个语句
WHEN OTHERS THEN
v_ErrorCode := SQLCODE;
-- Note the use of SUBSTR here.
v_ErrorText := SUBSTR(SQLERRM, 1, 200);
INSERT INTO log_table (code, message, info) VALUES
(v_ErrorCode, v_ErrorText, 'Oracle error occurred');
END;
注意,上面例子中的SQLCODE和SQLERRM是oracle定义的两个函数,其返回值是当前异常的错误码和错误描述。由于它们是函数,因此无法直接被使用,只能先将其返回值存放到一个变量中,然后再使用。
另外,每一个错误描述的长度,最大长度均为512个字节。