【转】 oracle exception总结(读书笔记)
2011年11月04日
一,基础-什么是异常情态?
1):exception即异常情态,如:
DECLARE
exptname EXCEPTION; --异常情态的定义
[PRAGMA EXCEPTION_INIT;] --异常情态与run time error number相关联
.
.
BEGIN
.
.
END;
每一个异常情态都【应当】有一个exception handler(异常处理器)与之对应,
从而在【代码执行部分】发生对应的异常情态(exception也可叫run time error)
时处理异常,而防止异常扩大。
当然你也可以只声明异常情态,不与相应的run time error number对应,
甚至没有对应的exception handler,这时的这个异常情态声明是没有意义的:
DECLARE
exptname EXCEPTION;
BEGIN
DBMS_OUTPUT.PUT_LINE('Hello World!');
END;
2):自定义与预定义异常
DECLARE
exptname EXCEPTION;
BEGIN
DBMS_OUTPUT.PUT_LINE('Hello World!');
RAISE exptname;
END;
上面只定义了异常情态,而没有对应的exception handler,所以RAISE时
会出现run time error,因为RAISE也是在BEGIN .. END之间的,所以也是
一个run time的实际执行部分。
预定义异常:
BEGIN
RAISE CASE_NOT_FOUND;
EXCEPTION WHEN CASE_NOT_FOUND then
DBMS_OUTPUT.PUT_LINE('case语句没有正确结束!');
END;
这些预定义的异常都是在standard包(这个包中有大部分系统函数,如:left,right等)中预先定义的,你也可以在包中定义自己的
异常:
CREATE OR REPLACE PACKAGE test_pkg AS
exptname EXCEPTION;
END;
BEGIN
RAISE test_pkg.exptname;
EXCEPTION WHEN test_pkg.exptname THEN
DBMS_OUTPUT.PUT_LINE('触发了自定义异常!');
END;
3):异常情态的流程
注意:异常情态是在定义部分定义的(预定义异常除外),执行部分(begin .. end中)触发的,exception handler
中处理的。
看完上面的流程你应该有一个疑问:定义部分和handler部分的异常又怎样捕获呢?
答案当然是在其包含块中捕获,看下面:
BEGIN
DECLARE
v_int INT:='ABC';
BEGIN
NULL;
EXCEPTION WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('I can only check then BEGIN .. END part error!'||chr(10)||'Other part i can''t check!');
END;
EXCEPTION WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('BEGIN .. END part have error occured!'||chr(10)||'Please check that part!');
END;
上面的父块就成功捕获了调用块中的定义部分的run time error,而被调用块的异常部分没有被执行;
其实很好理解,对于子块如果定义部分出现了错误,它的BEGIN .. END部分代码都不会被执行,
而handler只处理BEGIN .. END部分出现的异常情态,所以当然就捕获不到定义部分的异常。
对于异常handler部分出现的异常更好理解了,因为handler只要处理BEGIN .. END中的异常情态:
BEGIN
DECLARE
CURSOR test_cur IS SELECT 1 FROM DUAL;
BEGIN
RAISE CURSOR_ALREADY_OPEN;
EXCEPTION WHEN CURSOR_ALREADY_OPEN THEN
CLOSE test_cur;
WHEN INVALID_CURSOR THEN
DBMS_OUTPUT.PUT_LINE('游标已经关闭或者没有这个游标的声明!');
END;
EXCEPTION WHEN INVALID_CURSOR THEN
DBMS_OUTPUT.PUT_LINE('游标已经关闭或者没有这个游标的声明!');
END;
4):异常作用域
BEGIN
DECLARE
exptname EXCEPTION;
BEGIN
RAISE exptname;
END;
EXCEPTION WHEN exptname THEN
DBMS_OUTPUT.PUT_LINE('触发了子块中异常!');
END;
上面的语句是不能执行的,因为exptname的作用域只在子块中生效,
其实异常情态定义和变量定义一样,作用域生效原则和变量也是一样的。
鉴于上面的原因,如果有必要可以预定义自己的异常:
CREATE OR REPLACE PACKAGE test_pkg AS
exptname EXCEPTION;
END;
BEGIN
BEGIN
RAISE test_pkg.exptname;
END;
EXCEPTION WHEN test_pkg.exptname THEN
DBMS_OUTPUT.PUT_LINE('触发了子块中异常!');
END;
5):常见的预定义情态
INVALID_CURSOR --发生关闭已经关闭的游标或者不存在的游标时出现
CURSOR_ALREADY_OPEN
NO_DATA_FOUND --针对select .. into ..,没有返回行时,或者引用未初始化的plsql索引表
TOO_MANY_ROWS --select .. into 返回多行
INVALID_NUMBER与VALID_ERROR --字符串不能转换成数字错误
过程性语句中字符串不能转换成数字,会引发VALUE_ERROR异常情态:
DECLARE
v_int INT;
v_varchar2 varchar2(100);
BEGIN
v_varchar2:='a12';
v_int:=v_varchar2;
EXCEPTION WHEN VALUE_ERROR THEN
v_int:=REGEXP_REPLACE(v_varchar2,'[^[:digit:]]','' );
DBMS_OUTPUT.PUT_LINE(v_int);
END;
sql语句中则会引发INVALID_NUMBER异常情态:
CREATE TABLE test(x INT);
BEGIN
INSERT INTO TEST VALUES('AB123');
EXCEPTION WHEN INVALID_NUMBER THEN
DBMS_OUTPUT.PUT_LINE('无效数字!');
END;
还有两个特殊的异常:
PGROGRAM_ERROR和STORAGE_ERROR
如果出现STORAGE_ERROR则证明内在不够,如果出现PROGRAM_ERROR则说明你要联系oracle
了,因为program_error是PL/SQL引擎出现错误。
6):异常handler关键字or,多异常情况匹配
BEGIN
RAISE VALUE_ERROR;
RAISE INVALID_NUMBER; --注意:这行不执行,因为只要异常情态触发了,就不再返回BEGIN .. END部分执行下面的代码了
EXCEPTION WHEN INVALID_NUMBER OR VALUE_ERROR THEN
DBMS_OUTPUT.PUT_LINE('Not numeric!');
END;
7):sqlcode与sqlerrm【过程性函数】
DECLARE
x VARCHAR(200);
y VARCHAR2(200);
BEGIN
RAISE NO_DATA_FOUND;
EXCEPTION WHEN OTHERS THEN
x:=SQLCODE;
y:=SQLERRM(SQLCODE);
INSERT INTO test VALUES(x,y);
insert into test VALUES(SYSDATE,SYSTIMESTAMP);
END;
注意,因为sqlcode与sqlerrm是过程性的函数,所以不可以在sql语句下直接使用,不能像sysdate等系统函数。
DECLARE
x VARCHAR2(100);
y VARCHAR2(200);
BEGIN
x:=SQLCODE;
y:=SQLERRM(0);
--SELECT SQLERRM(0) INTO y FROM DUAL; 不能在sql中使用过程性函数,可能跟纯度级别有关系吧
DBMS_OUTPUT.PUT_LINE(x||chr(9)||y);
END;
且sqlerrm只会返回系统内部的oracle错误信息,不会返回用户自定义的信息:
BEGIN
RAISE NO_DATA_FOUND;
EXCEPTION WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Hello '||SQLERRM);
END;
如果返回用户定义的消息,岂不死循环了。
二,异常传播机制
其实在上面的叙述中都已经一一详细介绍过。
三,plsql常用异常处理模块--实际应用部分
1):dbms_utility.format_call_stack与dbms_utility.format_error_stack简单使用
create or replace procedure error_test1 as
begin
DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.FORMAT_CALL_STAC K);
raise value_error;
end;
create or replace procedure error_test2 as
begin
error_test1;
exception when others then
DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.FORMAT_ERROR_STA CK);
end;
注意:想得到正确的调用堆栈要把dbms_utility.format_call_stack放在最终调用子程序中,
因为调用方向总是从外向里调用,所以要得到详细的堆栈当然要沿着调用路线。
错误堆栈则相反,因为异常总是按从里向外路线传递,所以想捕获整个错误堆栈就要在祖块捕获。
2):在《Oracle 8i PL/SQL程序设计》一书的P265有一个详细的利用dbms_utility.format_error_stack和dbms_utility.format_call_stack的
例子程序,非常不错,可以详细的看一看。
发表评论
-
周线选
2012-01-20 11:11 824周线选 21小时前 大盘30日线起码走平 周 ... -
2011年全国大学生数学建模竞赛c题个人分析
2012-01-20 11:11 9522011年全国大学生数学建模竞赛c题个人分析 2011年09 ... -
冲刺一答案
2012-01-20 11:11 550冲刺一答案 23小时前 冲刺押题卷一 政治冲刺试卷 ... -
C# 线程手册 第二章 .net 中的线程 创建一个线程
2012-01-20 11:10 577C# 线程手册 第二章 .net 中的线程 创建一个线程 2 ... -
单元过关----捷达学校中级《财务管理》测试题(6)
2012-01-20 11:10 1813单元过关----捷达学校中 ... -
php编译mysql configure: error: mysql configure failed. Please check config.log for more information
2012-01-19 16:01 1286php编译mysql configure: error: my ... -
Error in symeqn called by dstmak. Please send data to your ANSYS Technical S
2012-01-19 16:01 1787Error in symeqn called by dstma ... -
linux设备模型深探(2)【转】
2012-01-19 16:01 829linux设备模型深探(2)【转】 2011年12月07日 ... -
C#实现Xml日志记录文件的最优方案
2012-01-19 16:01 997C#实现Xml日志记录文件的最优方案 2012年01月05日 ... -
JavaScript跨域总结与解决办法
2012-01-17 05:53 516JavaScript跨域总结与解决 ... -
关于fckeditor在服务器上无法上传图片的问题
2012-01-17 05:53 962关于fckeditor在服务器上无法上传图片的问题 2010 ... -
FCKEditor 2.6.3 ASP.NET 图片上传 停留在进度条问题解决
2012-01-17 05:53 782FCKEditor 2.6.3 ASP.NET 图片上传 停留 ... -
寻访福建最美乡村之 南安蔡浅古大厝
2012-01-16 04:40 1187寻访福建最美乡村之 ... -
专项训练十七
2012-01-16 04:39 676专项训练十七 2012年01 ...
相关推荐
### Oracle PL/SQL编程核心知识点解析 #### 一、创建基本表与操作 在Oracle数据库中,使用PL/SQL进行数据库编程前,首先需掌握如何创建表与进行基本的CRUD(创建、读取、更新、删除)操作。示例中的`CREATE TABLE`...
Oracle存储过程是数据库管理系统Oracle中的一种重要特性,它允许开发者编写一组SQL和PL/SQL语句,形成一个可重用的程序单元。存储过程的概念类似于高级编程语言中的模块,通过参数传递来实现数据的交互,体现了模块...
标题中提到的“oracle pl的学习笔记”指的是对Oracle PL/SQL(Procedural Language/SQL)的学习笔记。PL/SQL是Oracle数据库中用于存储过程、函数、触发器和游标编程的一种过程化SQL语言的扩展。学习PL/SQL可以帮助...
Oracle PL/SQL 基础知识点总结 Oracle PL/SQL 是一种基于 Oracle 关系数据库管理系统的过程语言,主要用于编写存储过程、函数和触发器等。下面是 Oracle PL/SQL 的基础知识点总结: 一、变量命名规则 * 变量名以...
这些"oracle课上笔记"包含了学习Oracle数据库所需的重要概念和技术,包括SQL、PL/SQL以及Proc/C++的相关内容。 首先,SQL(Structured Query Language)是用于管理关系数据库的语言。在`oracleday01.txt`和`...
以下是一些从“学习Oracle笔记”中提取的关键知识点: 1. **DECODE 函数**:DECODE 函数在Oracle SQL中用于替代简单的IF...ELSE逻辑。在示例中,`decode(sex, '男', 1, 0)` 意味着如果性别为'男',则返回1,否则...
总结来说,"Oracle学习笔记+代码"涵盖了Oracle数据库的基础和进阶内容,包括SQL语句的使用、PL/SQL编程以及通过Pro*C/C++进行数据库访问。通过深入学习和实践,你可以成为一个熟练的Oracle开发者,能够构建高效、...
以下是 Oracle 开发笔记的知识点总结: 序列建立 * 序列是一种特殊的数据库对象,可以生成唯一的编号。Oracle 中的序列是通过 CREATE SEQUENCE 语句创建的。 * 序列可以用于生成自增 ID 字段,例如在建表时将要建...
"Oracle培训18天老师笔记"很可能是对Oracle SQL和PL/SQL基础的深入学习资料,涵盖了数据库查询、数据管理以及程序设计等多个核心领域。下面将详细阐述这些知识点。 一、SQL(Structured Query Language)基础 SQL,...
"Oracle笔记proc代码等"这个标题和描述暗示了我们可能涉及到的是关于Oracle数据库的PL/SQL过程(PROC)编程相关的学习资料。PL/SQL是Oracle专有的SQL扩展,它允许开发者编写存储过程、函数、触发器等,以实现更复杂...
Oracle 常用命令举例 标题 基本语法 %type用法,%rowtype用法,TYPE用法 游标的使用 for 循环 loop循环 while循环 if / else 的用法 case 的用法 标题 错误定义 error的设定 exception用法 ...
总结,Oracle PL/SQ 提供了强大的数据库编程能力,通过存储过程、函数、触发器和包,开发者可以构建复杂的业务逻辑,确保数据的一致性和安全性。理解并熟练掌握这些概念对于 Oracle 数据库管理员和开发人员来说至关...
### Oracle PL/SQL知识点解析 #### 一、PL/SQL简介 PL/SQL(Procedural Language for ...以上内容总结了Oracle PL/SQL的一些基础知识和常用操作,通过这些示例可以帮助读者更好地理解和掌握PL/SQL的核心概念和用法。
### Oracle 10g知识点详解 #### 一、文件操作命令 在Oracle 10g中,可以通过一些特定的命令来进行文件的操作。 - **SAVE**: 用于保存数据到指定路径的文件。 - 示例:`SAVE C:\1.txt` 表示将数据保存到C盘根目录...
通过阅读“Oracle9i PLSQL 入门到精通”这本书,读者可以系统地学习如何使用PLSQL进行数据库编程,从简单的数据操作到复杂的业务逻辑实现,逐步提升为数据库专家。书中的实例和实践项目将帮助读者巩固理论知识,提高...