---------------------------pl/sql中的异常处理---------
/*
分三种异常:预定义异常、非预定义异常、自定义异常
*/
--捕获预定义异常
DECLARE
r NUMBER(10,0);
BEGIN
r := 100/0;
EXCEPTION
-- zero_divide 除数为0的异常
WHEN zero_divide THEN
dbms_output.put_line('除数为0,捕获到此异常');
END;
/* oracle 共有25种预定义异常,常见的预定义异常有:
1、 too_many_rows select..into 返回多条记录
2、 no_data_found select..into 没有返回记录
3、 zero_divide 除数为0 的异常
4、case_not_found case语句中,when没有匹配的条件也没有else 触发该异常。
5、storage_error 内存溢出 等异常
6、cursor_already_open 打开已经打开的游标
7. timeout_on_resource 等待资源超时
8. dup_val_on_index 表中唯一的索引对应的列中出现重复值
*/
------非预定义异常
/*
用于处理预定义异常所不能处理的ORACLE错误。
使用非预定义异常包括三步:
一、首先定义异常;
二、使用PROGMA EXCEPTION_INIT(EXCEPTION_NAME,EXCEPTION_NUMBER)过程在所定义的异常变量与ORACLE错误代码之间建立关联,这就要求用户知道可能出现的错误号(可以通过异常函数SQLCODE、SQLERRM和RAISE_APPLICATION_ERROR);
三、在异常处理部分捕捉并处理异常。
*/
--模拟处理预定义异常
CREATE TABLE t1 (
ID NUMBER(10,0),
age NUMBER(3,0),
CONSTRAINT t1_pk PRIMARY KEY (ID)
);
ALTER TABLE t1 ADD CONSTRAINT s_pk UNIQUE (age);
INSERT INTO t1 VALUES (2,2);
CREATE TABLE t2 (
ID NUMBER(3,0) NOT NULL UNIQUE,
NAME VARCHAR2(10),
CONSTRAINT t2_fk FOREIGN KEY (ID) REFERENCES t1(age)
);
DECLARE
m NUMBER(10,0) :=10;
n VARCHAR2(100):='纳兰';
---定义异常名称
unique_exp EXCEPTION;
--把异常名称和数据库错误号关联
PRAGMA Exception_Init(unique_exp,-2291);
BEGIN
INSERT INTO t2 (ID,NAME)VALUES (m,n);
COMMIT;
--捕获异常
EXCEPTION
WHEN unique_exp
THEN
dbms_output.put_line('没有找到父项关键字,违反唯一约束条件');
ROLLBACK;
END;
------自定义异常处理
/*
自定义异常为了处理一些业务逻辑,比如 对年龄非负数等一些符合生产环境的情况
*/
INSERT INTO t1 VALUES (4,-10);
COMMIT;
DECLARE
age NUMBER;
--异常名称
not_navigate EXCEPTION;
--绑定异常名称
PRAGMA EXCEPTION_INIT(not_navigate,-2014);
BEGIN
SELECT age INTO age FROM t1 WHERE ID=5;
IF age<0 THEN
--显式的抛出异常 用raise
RAISE not_navigate;
END IF;
dbms_output.put_line('输出年龄为:'||age);
EXCEPTION
WHEN not_navigate THEN
dbms_output.put_line('年龄不能为负数');
WHEN no_data_found THEN
dbms_output.put_line('没有找到该条记录');
WHEN TOO_many_rows THEN
dbms_output.put_line('太多记录数');
END;
另附上转帖的oracle的预定义异常:
命名的系统异常 | 产生原因 | Oracle Error SQLCODE Value |
ACCESS_INTO_NULL | 未定义对象 | ORA-06530 -6530 |
CASE_NOT_FOUND | CASE 中若未包含相应的WHEN ,并且没有设置 ELSE时 | ORA-06592 -6592 |
COLLECTION_IS_NULL | 集合元素未初始化 | ORA-06531 -6531 |
CURSER_ALREADY_OPEN | 游标已经打开 | ORA-06511 -6511 |
DUP_VAL_ON_INDEX | 唯一索引对应的列上有重复的值 | ORA-00001 -1 |
INVALID_NUMBER | 在不合法的游标上进行操作 | ORA-01722 -1722 |
INVALID_CURSOR | 在不合法的游标上进行操作 | ORA-01001 -1001 |
NO_DATA_FOUND | 使用 select into 未返回行,或应用索引表未初始化的元素时 | ORA-01403 +100 |
TOO_MANY_ROWS | 执行 select into 时,结果集超过一行 | ORA-01422 -1422 |
ZERO_DIVIDE | 除数为 0 | ORA-01476 -1476 |
SUBSCRIPT_BEYOND_COUNT | 元素下标超过嵌套表或VARRAY 的最大值 | ORA-06533 -6533 |
SUBSCRIPT_OUTSIDE_LIMIT | 使用嵌套表或 VARRAY 时,将下标指定为负数 | ORA-06532 -6532 |
VALUE_ERROR | 赋值时,变量长度不足以容纳实际数据 | ORA-06502 -6502 |
LOGIN_DENIED | PL/SQL 应用程序连接到oracle 数据库时,提供了不正确的用户名或密码 | ORA-01017 -1017 |
NOT_LOGGED_ON | PL/SQL 应用程序在没有连接oralce数据库的情况下访问数据 | ORA-01012 -1012 |
PROGRAM_ERROR | PL/SQL 内部问题,可能需要重装数据字典& pl./SQL 系统包 | ORA-06501 -6501 |
ROWTYPE_MISMATCH | 宿主游标变量与 PL/SQL 游标变量的返回类型不兼容 | ORA-06504 -6504 |
SELF_IS_NULL | 使用对象类型时,在 null 对象上调用对象方法 | ORA-30625 -30625 |
STORAGE_ERROR | 运行 PL/SQL 时,超出内存空间 | ORA-30625 -30625 |
SYS_INVALID_ID | 无效的 ROWID 字符串 | ORA-01410 -1410 |
TIMEOUT_ON_RESOURCE | Oracle 在等待资源时超时 | ORA-00051 -51 |
Brief descriptions of the predefined exceptions follow:
Exception Raised when ...
ACCESS_INTO_NULL Your program attempts to assign values to the attributes of an uninitialized (atomically null) object.
CASE_NOT_FOUND None of the choices in the WHEN clauses of a CASE statement is selected, and there is no ELSE clause.
COLLECTION_IS_NULL Your program attempts to apply collection methods other than EXISTS to an uninitialized (atomically null) nested table or varray, or the program attempts to assign values to the elements of an uninitialized nested table or varray.
CURSOR_ALREADY_OPEN Your program attempts to open an alrea*** open cursor. A cursor must be closed before it can be reopened. A cursor FOR loop automatically opens the cursor to which it refers. So, your program cannot open that cursor inside the loop.
DUP_VAL_ON_INDEX Your program attempts to store duplicate values in a database column that is constrained by a unique index.
INVALID_CURSOR Your program attempts an illegal cursor operation such as closing an unopened cursor.
INVALID_NUMBER In a SQL statement, the conversion of a character st*** into a number fails because the st*** does not represent a valid number. (In procedural statements, VALUE_ERROR is raised.) This exception is also raised when the LIMIT-clause expression in a bulk FETCH statement does not evaluate to a positive number.
LOGIN_DENIED Your program attempts to log on to Oracle with an invalid username and/or password.
NO_DATA_FOUND A SELECT INTO statement returns no rows, or your program references a deleted element in a nested table or an uninitialized element in an index-by table. SQL aggregate functions such as AVG and SUM always return a value or a null. So, a SELECT INTO statement that calls an aggregate function never raises NO_DATA_FOUND. The FETCH statement is expected to return no rows eventually, so when that happens, no exception is raised.
NOT_LOGGED_ON Your program issues a database call without being connected to Oracle.
PROGRAM_ERROR PL/SQL has an internal problem.
ROWTYPE_MISMATCH The host cursor variable and PL/SQL cursor variable involved in an assignment have incompatible return types. For example, when an open host cursor variable is passed to a stored subprogram, the return types of the actual and formal parameters must be compatible.
SELF_IS_NULL Your program attempts to call a MEMBER method on a null instance. That is, the built-in parameter SELF (which is always the first parameter passed to a MEMBER method) is null.
STORAGE_ERROR PL/SQL runs out of memory or memory has been corrupted.
SUBSCRIPT_BEYOND_COUNT Your program references a nested table or varray element using an index number larger than the number of elements in the collection.
SUBSCRIPT_OUTSIDE_LIMIT Your program references a nested table or varray element using an index number (-1 for example) that is outside the legal range.
SYS_INVALID_ROWID The conversion of a character st*** into a universal rowid fails because the character st*** does not represent a valid rowid.
TIMEOUT_ON_RESOURCE A time-out occurs while Oracle is waiting for a resource.
TOO_MANY_ROWS A SELECT INTO statement returns more than one row.
VALUE_ERROR An arithmetic, conversion, truncation, or size-constraint error occurs. For example, when your program selects a column value into a character variable, if the value is longer than the declared length of the variable, PL/SQL aborts the assignment and raises VALUE_ERROR. In procedural statements, VALUE_ERROR is raised if the conversion of a character st*** into a number fails. (In SQL statements, INVALID_NUMBER is raised.)
ZERO_DIVIDE Your program attempts to divide a number by zero.