常用EXCEPTION异常及处理
NO_DATA_FOUND 当 SQL 游标返回 0 行时; (SQL%NOTFOUND)
TOO_MANY_ROWS 当 SELECT INTO语句返回多行时;
INVALID_NUMBER 未能将 SQL语句中字符串成功转换成数字;
ZERO_DIVIDE 执行了除以0 操作;
CURSOR_ALREADY_OPEN 试图打开一个已打开的游标;
INVALID_CURSOR 执行了非法游标操作,如试图关闭一个已关闭的游标;
STORAGE_ERROR 由于PL/SQL 内存溢出导致内部 PL/SQL 错误发生;
TIMEOUT_ON_RESORCE 等待资源超时;
DUP_VAL_ON_INDEX 违反唯一性约束;
TRANSACTION_BACKED_OUT 由于死锁使事务回滚;
PROGRAM_ERROR 内部 PL/SQL 错误,这属于系统软件问题
VALUE_ERROR 由于在过程性语句中出现转换、截断、算术错误而产生的异常;
ROWTYPE_MISMATCH 一个主游标变量和 PL/SQL游标变量类型不匹配;
ACCESS_INTO_NULL 试图给一个 NULL 对象的属性赋值;
COLLECTION_IS_NULL 试图对 NULL 的 PL/SQL 或变长数组执行 EXISTS 以外的操作;
SUBCRIPT_OUTSIDE_LIMIT 引用的嵌套表或变长数组索引超出了其申明范围;
SUBCRIPT_BEYOND_COUNT 引用的嵌套表或变长数组索引大于了嵌套表或嵌套表中元素 个数;
NO_LOGGED_ON 没有连接 Oracle数据库;
LOGIN_DENIED 错误的用户名或口令;
在 INSERT, UPDATE 和 DELETE语句执行没有行返回时是不会抛出异常的,这个时候我们必须显示的检查 SQL%NOTFOUND 的值以判断是否有无数据返回的错误。对于这种语 句还可以用SQL%ROWCOUNT(判断该SQL语句处理数据的行数)和SQL%FOUND来获得执行状态。
自定义异常
自定义异常的申明:
PRAGMA EXCEPTION_INIT(exception_name, Oracle_error_number);
Exception_name 是预先申明的异常名,Oracle_error_number 是错误号,这条命令必须写在定义部分。
Declare
V_code author.name%type;
E_TooLarge EXCEPTION;
PRAGMA EXCEPTION_INIT(E_TooLarge, -1401);
用户自定的异常要在申明后才能产生,我们可以用 RAISE_APPLICATION_ERROR 函数直接产生异常:
RAISE_APPLICATION_ERROR(error_number, error_message, [keep_errors]);
其中 error_number 是错误号,值在-20000~-20999 之间,error_message 是错误消息文本, 最大不超过 512 字节;keep_errors 为 BOOLEAN 值可选参数,为 TURE 则新的错误将加到已有 错误列表之后,为 FALSE 则新的错误将代替当前的错误列表。
WHEN e_error1 OR e_error2 THEN
RAISE 语句还可以不带参数的使用,则当前的异常被传递到块外。
SQLCODE 和 SQLERRM 函数
SQLCODE 对应返回的错误代码,SQLERRM 返回的是错误信息。
注意,如果使用 EXCEPTION_INIT 预编译指令声明与 Oracle 错误相连的自定义异常,则SQLCODE 和 SQLERRM 返回对应的 Oracle错误代码和相应的错误信息,而不是返回“+1”和“User-Dfined Exception”。 调用 SQLERRM 时可以带一个数字参数,返回值是与这个数字参数相关的文本。
例如,如 果 SQLERRM 的参数是 0,则返回消息是“ORA-0000 : normal , successful completion”。
在FROM开发中的异常及处理
Errors in Oracle Forms PL/SQL
使用FND_MESSAGE来显示错误信息,然后抛出FORM_TRIGGER_FAILURE来停止处理过程:
IF (error_condition) THEN
fnd_message.set_name(appl_short_name, message_name);
fnd_message.error;
RAISE FORM_TRIGGER_FAILURE;
END IF;
8.3.2 Errors in Stored Procedures
使用存储过程包FND_MESSAGE.SET_NAME来设置错误消息,然后用APP_EXCEPTIO N. RAISE_EXCEPTION来停止处理过程:
IF (error_condition) THEN
fnd_message.set_name(appl_short_name, message_name);
APP_EXCEPTION.RAISE_EXCEPTION;
END IF;
该FORM中的存储过程无需处理该错误异常,在FORM出发器ON–ERROR中的代码会自动 侦测到该存储器错误,抓取到异常并显示错误信息。
Testing FORM_SUCCESS, FORM_FAILURE and FORM_FATAL
我们要意识到每当我们编译当前触发器时,可能会引起某些值的改变时,从而又会引起其 他触发器的运行,为避免错误我们就应该测试 FORM_SUCCESS,FORM_FAILURE或者 FO RM_FATAL的值。
例如:
GO_ITEM(’emp.empno’);
IF FORM_FAILURE THEN
RAISE FORM_TRIGGER_FAILURE;
END IF;
其中GO_ITEM会触发别的触发器, 例如WHEN–NEW–ITEM–INSTANCE,从而GO_ITEM执行可能会出错,但最后一个触发的触发器可能又是成功的,这就意味这FORM_FAILURE值是FLASE从而无法引起异常而捕获该错误,如下的代码就可以避免这样的问题:
GO_ITEM(’EMP.EMPNO’);
IF :SYSTEM.CURSOR_ITEM != ’EMP.EMPNO’ THEN
–– No need to show an error, because Oracle Forms
–– some other condition that caused the GO_ITEM
–– to fail.
RAISE FORM_TRIGGER_FAILURE;
END IF;
Avoid RAISE_APPLICATION_ERROR
切忌在FORM开发中不要使用RAISE_APPLICATION_ERROR,因为他与服务器端的异常处理模式相冲突。