Oracle PL/SQL语言初级教程之异常处理
来源:互联网 发布:青云志坐骑进阶数据 编辑:程序博客网 时间:2024/05/21 07:51
Oracle PL/SQL语言初级教程之异常处理
PL/SQL处理异常不同于其他程式语言的错误管理方法,PL/SQL的异常处理机制和ADA很相似,有一个处理错误的全包含方法。当发生错误时,程式无条件转到异常处理部分,这就需要代码要很干净并把错误处理部分和程式的其他部分分开。oracle允许声明其他异常条件类型以扩展错误/异常处理。这种扩展使PL/SQL的异常处理很灵活。
当一个运行时错误发生时,称为一个异常被抛出。PL/SQL程式编译时的错误不是能被处理得异常,只有在运行时的异常能被处理。在PL/SQL程式设计中异常的抛出和处理是很重要的内容。
抛出异常
由三种方式抛出异常
. 通过PL/SQL运行时引擎
. 使用RAISE语句
. 调用RAISE_APPLICATION_ERROR存储过程
当数据库或PL/SQL在运行时发生错误时,一个异常被PL/SQL运行时引擎自动抛出。异常也能够通过RAISE语句抛出
RAISE exception_name;
显式抛出异常是程式员处理声明的异常的习惯用法,但RAISE不限于声明了的异常,他能够抛出任何任何异常。例如,您希望用TIMEOUT_ON_RESOURCE错误检测新的运行时异常处理器,您只需简单的在程式中使用下面的语句: 中国网管论坛
RAISE TIMEOUT_ON_RESOUCE;
下面看一个订单输入系统,当库存小于订单时抛出一个inventory_too_low异常。
DECLARE
inventory_too_low EXCEPTION;
---其他声明语句
BEGIN
.
.
IF order_rec.qty>inventory_rec.qty THEN
RAISE inventory_too_low;
END IF
.
.
EXCEPTION
WHEN inventory_too_low THEN
order_rec.staus:='backordered';
replenish_inventory(inventory_nbr=>
inventory_rec.sku,min_amount=>order_rec.qty-inventory_rec.qty);
END;
这里replenish_inventory是个触发器。
处理异常
PL/SQL程式块的异常部分包含了程式处理错误的代码,当异常被抛出时,一个异常陷阱就自动发生,程式控制离开执行部分转入异常部分,一旦程式进入异常部分就不能再回到同一块的执行部分。下面是异常部分的一般语法:
EXCEPTION DL.bitsCN.com网管软件下载
WHEN exception_name THEN
Code for handing exception_name
[WHEN another_exception THEN
Code for handing another_exception]
[WHEN others THEN
code for handing any other exception.]
用户必须在单独的WHEN子串中为每个异常设计异常处理代码,WHEN OTHERS子串必须放置在最后面作为缺省处理器处理没有显式处理的异常。当异常发生时,控制转到异常部分,ORACLE查找当前异常相应的WHEN..THEN语句,捕获异常,THEN之后的代码被执行,假如错误陷阱代码只是退出相应的嵌套块,那么程式将继续执行内部块END后面的语句。假如没有找到相应的异常陷阱,那么将执行WHEN OTHERS。在异常部分WHEN 子串没有数量限制。
EXCEPTION
WHEN inventory_too_low THEN
order_rec.staus:='backordered';
replenish_inventory(inventory_nbr=>
inventory_rec.sku,min_amount=>order_rec.qty-inventory_rec.qty);
WHEN discontinued_item THEN
--code for discontinued_item processing
WHEN zero_divide THEN
--code for zero_divide
WHEN OTHERS THEN
--code for any other exception
END;
当异常抛出后,控制无条件转到异常部分,这就意味着控制不能回到异常发生的位置,当异常被处理和解决后,控制返回到上一层执行部分的下一条语句。
BEGIN
DECLARE
bad_credit;
BEGIN
RAISE bad_credit;
--发生异常,控制转向;
EXCEPTION
WHEN bad_credit THEN
dbms_output.put_line('bad_credit');
END;
--bad_credit异常处理后,控制转到这里
EXCEPTION
WHEN OTHERS THEN
--控制不会从bad_credit异常转到这里
--因为bad_credit已被处理
END;
当异常发生时,在块的内部没有该异常处理器时,控制将转到或传播到上一层块的异常处理部分。 bitsCN.nET中国网管博客
BEGIN
DECLARE ---内部块开始
bad_credit;
BEGIN
RAISE bad_credit;
--发生异常,控制转向;
EXCEPTION
WHEN ZERO_DIVIDE THEN --不能处理bad_credite异常
dbms_output.put_line('divide by zero error');
END --结束内部块
--控制不能到达这里,因为异常没有解决;
--异常部分
EXCEPTION
WHEN OTHERS THEN
--由于bad_credit没有解决,控制将转到这里
END;
异常传播
没有处理的异常将沿检测异常调用程式传播到外面,当异常被处理并解决或到达程式最外层传播停止。
在声明部分抛出的异常将控制转到上一层的异常部分。
BEGIN
executable statements
BEGIN
today DATE:='SYADATE'; --ERRROR
BEGIN --内部块开始
dbms_output.put_line('this line will not execute');
www_bitscn_com
EXCEPTION
WHEN OTHERS THEN
--异常不会在这里处理
END;--内部块结束
EXCEPTION
WHEN OTHERS THEN
处理异常
END
执行部分抛出的异常将首先传递到同一块的异常部分,假如在同一块的异常部分没有处理这个异常的处理器,那么异常将会传播到上一层的异常部分中,一直到最外层。
在异常部分抛出的异常将控制转到上一层的异常部分。
处理异常将停止异常的传播和解决。有时用户希望在错误发生时,程式仍然能执行一些动作,要达到这个目的,能够把希望执行的动作放在异常处理器中,然后执行不带参数的RAISE语句,RAISE语句将重新抛出出现的异常,允许他继续传播。
DECLARE
order_too_old EXCEPTION;
BEGIN
RAISE order_too_old;
EXCEPTION
WHEN order_too_old THEN
DECLARE
file_handle UTL_FILE.FILE_TYPE;
BEGIN
--open file
file_handle:=UTL_FILE.FOPEN
(location=>'/ora01/app/oracle/admin/test/utlsir'
,filename=>'error.log'
.open_mode=>'W');
--write error stack
UTL_FILE.PUT_LINE(filehandle,
DBMS_UTILITY.FORMAT_ERROR_STACK);
--write the call stack
UTL_FILE.PUT_LINE(filehandle,
DBMS_UTILITY.FORMAT_CALL_STACK);
--close error log
UTL_FILE.FCLOSE(file_handle);
RAISE; --re-raise the exception
END
END
假如从FORMAT_XXX_STACK输出一个很大的值,那么使用DBMS_OUTPUT或UTL_FILE显示错误或调用堆的异常部分自身也会抛出异常,这两个堆常规下最多能返回2000字节,但utl_file.put_line被限制在1000字节以内,而dbms_output.put_line限制在512字节内。假如使用前面的代码并且不允许这种可能性,那么在异常处理器中将抛出一个未处理的异常。
GOTO语句不能用于将控制从执行部分传递到异常部分或反之。
已命名异常
在PL/SQL块的异常部分只有已命名的异常才能被WHEN子串处理,ORACLE包含了一系列已命名的异常,这些异常都声明在STANDARD包中,这些内建异常在这里就不一一讲述,有兴趣的读者能够查阅有关资料。
oracle 系统预定义异常表
Exception Oracle Error SQLCODE Value
ACCESS_INTO_NULL ORA-06530 -6530
CASE_NOT_FOUND ORA-06592 -6592
COLLECTION_IS_NULL ORA-06531 -6531
CURSOR_ALREADY_OPEN ORA-06511 -6511
DUP_VAL_ON_INDEX ORA-00001 -1
INVALID_CURSOR ORA-01001 -1001
INVALID_NUMBER ORA-01722 -1722
LOGIN_DENIED ORA-01017 -1017
NO_DATA_FOUND ORA-01403 +100
NOT_LOGGED_ON ORA-01012 -1012
PROGRAM_ERROR ORA-06501 -6501
ROWTYPE_MISMATCH ORA-06504 -6504
SELF_IS_NULL ORA-30625 -30625
STORAGE_ERROR ORA-06500 -6500
SUBSCRIPT_BEYOND_COUNT ORA-06533 -6533
SUBSCRIPT_OUTSIDE_LIMIT ORA-06532 -6532
SYS_INVALID_ROWID ORA-01410 -1410
TIMEOUT_ON_RESOURCE ORA-00051 -51
TOO_MANY_ROWS ORA-01422 -1422
VALUE_ERROR ORA-06502 -6502
ZERO_DIVIDE ORA-01476 -1476
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.
- Oracle PL/SQL语言初级教程之异常处理
- Oracle PL/SQL语言初级教程之异常处理
- Oracle PL/SQL语言初级教程之异常处理
- Oracle PL/SQL语言初级教程之游标
- Oracle PL/SQL语言初级教程
- Oracle PL/SQL语言初级教程
- Oracle PL/SQL语言初级教程
- Oracle PL/SQL语言初级教程之操作和控制语言
- oracle pl/sql语言初级教程之过程和函数
- Oracle PL/SQL语言初级教程之完整性约束
- Oracle PL/SQL语言初级教程之过程和函数
- Oracle PL/SQL语言初级教程之表和视图
- Oracle PL/SQL语言初级教程之完整性约束
- Oracle PL/SQL语言初级教程之表和视图
- Oracle数据库之PL/SQL异常处理
- Oracle:pl/sql 异常处理
- Oracle:pl/sql 异常处理
- Oracle PL/SQL异常处理
- 在MySQL中修改数据库表结构
- 利用中断方式通讯的测试程序
- like 字符串与变量的使用方法
- 随机环境下系统性能调优指南
- 想做好男人必懂的……
- Oracle PL/SQL语言初级教程之异常处理
- 泛型编程
- 《商业周刊》:2009年传媒业十大预言
- 打个招呼
- 无需.NET Framework环境运行.NET编写的软件
- Physically Based Modeling: Particle System Dynamics(粒子运动)
- JDBC/ODBC/.NET连接数据库/数据文件的连接字符串大全
- 监视未使用索引
- 安装VS2008的SP1之后的BUG补丁