`
rhj485hm
  • 浏览: 14386 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

【转】 oracle exception总结(读书笔记)

 
阅读更多

【转】 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的
  例子程序,非常不错,可以详细的看一看。
分享到:
评论

相关推荐

    oracle plsql编程学习笔记

    ### Oracle PL/SQL编程核心知识点解析 #### 一、创建基本表与操作 在Oracle数据库中,使用PL/SQL进行数据库编程前,首先需掌握如何创建表与进行基本的CRUD(创建、读取、更新、删除)操作。示例中的`CREATE TABLE`...

    oracle存储过程笔记

    Oracle存储过程是数据库管理系统Oracle中的一种重要特性,它允许开发者编写一组SQL和PL/SQL语句,形成一个可重用的程序单元。存储过程的概念类似于高级编程语言中的模块,通过参数传递来实现数据的交互,体现了模块...

    oracle pl的学习笔记

    标题中提到的“oracle pl的学习笔记”指的是对Oracle PL/SQL(Procedural Language/SQL)的学习笔记。PL/SQL是Oracle数据库中用于存储过程、函数、触发器和游标编程的一种过程化SQL语言的扩展。学习PL/SQL可以帮助...

    oracle plsql 菜鸟学习笔记

    Oracle PL/SQL 基础知识点总结 Oracle PL/SQL 是一种基于 Oracle 关系数据库管理系统的过程语言,主要用于编写存储过程、函数和触发器等。下面是 Oracle PL/SQL 的基础知识点总结: 一、变量命名规则 * 变量名以...

    oracle课上笔记

    这些"oracle课上笔记"包含了学习Oracle数据库所需的重要概念和技术,包括SQL、PL/SQL以及Proc/C++的相关内容。 首先,SQL(Structured Query Language)是用于管理关系数据库的语言。在`oracleday01.txt`和`...

    学习oracle笔记(word版本)

    以下是一些从“学习Oracle笔记”中提取的关键知识点: 1. **DECODE 函数**:DECODE 函数在Oracle SQL中用于替代简单的IF...ELSE逻辑。在示例中,`decode(sex, '男', 1, 0)` 意味着如果性别为'男',则返回1,否则...

    oracle学习笔记+代码

    总结来说,"Oracle学习笔记+代码"涵盖了Oracle数据库的基础和进阶内容,包括SQL语句的使用、PL/SQL编程以及通过Pro*C/C++进行数据库访问。通过深入学习和实践,你可以成为一个熟练的Oracle开发者,能够构建高效、...

    Oracle开发笔记

    以下是 Oracle 开发笔记的知识点总结: 序列建立 * 序列是一种特殊的数据库对象,可以生成唯一的编号。Oracle 中的序列是通过 CREATE SEQUENCE 语句创建的。 * 序列可以用于生成自增 ID 字段,例如在建表时将要建...

    oracle培训18天老师笔记

    "Oracle培训18天老师笔记"很可能是对Oracle SQL和PL/SQL基础的深入学习资料,涵盖了数据库查询、数据管理以及程序设计等多个核心领域。下面将详细阐述这些知识点。 一、SQL(Structured Query Language)基础 SQL,...

    oracle笔记proc代码等

    "Oracle笔记proc代码等"这个标题和描述暗示了我们可能涉及到的是关于Oracle数据库的PL/SQL过程(PROC)编程相关的学习资料。PL/SQL是Oracle专有的SQL扩展,它允许开发者编写存储过程、函数、触发器等,以实现更复杂...

    Oracle_plsql基本语法笔记.txt

    Oracle 常用命令举例 标题 基本语法 %type用法,%rowtype用法,TYPE用法 游标的使用 for 循环 loop循环 while循环 if / else 的用法 case 的用法 标题 错误定义 error的设定 exception用法 ...

    关于ORACLE PL笔记

    总结,Oracle PL/SQ 提供了强大的数据库编程能力,通过存储过程、函数、触发器和包,开发者可以构建复杂的业务逻辑,确保数据的一致性和安全性。理解并熟练掌握这些概念对于 Oracle 数据库管理员和开发人员来说至关...

    oracle plsql课堂笔记

    ### Oracle PL/SQL知识点解析 #### 一、PL/SQL简介 PL/SQL(Procedural Language for ...以上内容总结了Oracle PL/SQL的一些基础知识和常用操作,通过这些示例可以帮助读者更好地理解和掌握PL/SQL的核心概念和用法。

    Oracle 10g笔记

    ### Oracle 10g知识点详解 #### 一、文件操作命令 在Oracle 10g中,可以通过一些特定的命令来进行文件的操作。 - **SAVE**: 用于保存数据到指定路径的文件。 - 示例:`SAVE C:\1.txt` 表示将数据保存到C盘根目录...

    Oracle9i PLSQL 入门到精通读书笔记

    通过阅读“Oracle9i PLSQL 入门到精通”这本书,读者可以系统地学习如何使用PLSQL进行数据库编程,从简单的数据操作到复杂的业务逻辑实现,逐步提升为数据库专家。书中的实例和实践项目将帮助读者巩固理论知识,提高...

Global site tag (gtag.js) - Google Analytics