PL/SQL异常处理方法
 
1:什么是异常处理:
PL/SQL提供一个功能去处理异常,在PL/SQL块中叫做异常处理,使用异常处理我们能够测试代码和避免异常退出。
PL/SQL异常信息包含三个部分:
      1:异常类型
       2:错误代码
       3:错误信息
通过处理异常我们能够确保PL/SQL块不突然的异常退出。
 
2:异常处理的结构
DECLARE
   Declaration section 
 BEGIN 
   Exception section 
 EXCEPTION 
 WHEN ex_name1 THEN 
    -Error handling statements 
 WHEN ex_name2 THEN 
    -Error handling statements 
 WHEN Others THEN 
   -Error handling statements 
END; 
例子:
when others 能够截取所有的异常,一般放在异常处理的最后。
以上代码解释: 当异常出现的时候,oracle寻找合适的when的异常类型执行异常。
 
异常处理的好例子: 除0异常:
[sql] 
SQL> DECLARE  
  2     stock_price NUMBER := 9.73;  
  3     net_earnings NUMBER := 0;  
  4     pe_ratio NUMBER;  
  5  BEGIN  
  6  -- Calculation might cause division-by-zero error.  
  7     pe_ratio := stock_price / net_earnings;  
  8     DBMS_OUTPUT.PUT_LINE('Price/earnings ratio = ' || pe_ratio);  
  9  EXCEPTION  -- exception handlers begin  
 10  -- Only one of the WHEN blocks is executed.  
 11     WHEN ZERO_DIVIDE THEN  -- handles 'division by zero' error  
 12        DBMS_OUTPUT.PUT_LINE('Company must have had zero earnings.');  
 13        pe_ratio := NULL;  
 14     WHEN OTHERS THEN  -- handles all other errors  
 15        DBMS_OUTPUT.PUT_LINE('Some other kind of error occurred.');  
 16        pe_ratio := NULL;  
 17  END;  -- exception handlers and block end here  
 18  /  
  
PL/SQL 过程已成功完成。  
  
SQL> set serveroutput on  
SQL> /  
Company must have had zero earnings.  
为了避免除0可以这样:
[sql] 
DECLARE  
   stock_price NUMBER := 9.73;  
   net_earnings NUMBER := 0;  
   pe_ratio NUMBER;  
BEGIN  
   pe_ratio :=  
      CASE net_earnings  
         WHEN 0 THEN NULL  
         ELSE stock_price / net_earnings  
      end;  
END;  
/  
 
 
如果有一个嵌套的PL/SQL块像这样:
 DELCARE
   Declaration section 
 BEGIN
    DECLARE
      Declaration section 
    BEGIN 
      Execution section 
    EXCEPTION 
      Exception section 
    END; 
 EXCEPTION
   Exception section 
 END; 
 
在以上例子中: 如果异常出现在内部的块中,内部异常处理块应该处理这个异常,如果内部处理块没有处理这个
异常,控制会转移它的上一级的PL/SQL块中,如果上一级也没有对应的异常处理块,程序将错误的结束。
 
3:异常的类型:
异常有三种: 
  a:系统命名的异常
  b:系统未命名的异常
  c:用户自定义的异常(这个没用过)
 
a:系统命名的异常:
当程序违反关系型数据库规则的时候,oracle的系统异常会自动出现,有一些系统异常出现的比较频繁,它们是预定义
异常,这样的异常都有一个名字。
例如:NO_DATA_FOUND 和 ZERO_DIVIDE都有名字的系统异常。
常见的有:
Oracle Exception Name  Oracle Error  Explanation
DUP_VAL_ON_INDEX  ORA-00001  You tried to execute an INSERT or UPDATE statement that has created a duplicate value in a field restricted by a unique index.
TIMEOUT_ON_RESOURCE  ORA-00051  You were waiting for a resource and you timed out.
TRANSACTION_BACKED_OUT  ORA-00061  The remote portion of a transaction has rolled back.
INVALID_CURSOR  ORA-01001  You tried to reference a cursor that does not yet exist. This may have happened because you've executed a FETCH cursor or CLOSE cursor before OPENing the cursor.
NOT_LOGGED_ON  ORA-01012  You tried to execute a call to Oracle before logging in.
LOGIN_DENIED  ORA-01017  You tried to log into Oracle with an invalid username/password combination.
NO_DATA_FOUND  ORA-01403  You tried one of the following:
You executed a SELECT INTO statement and no rows were returned.
You referenced an uninitialized row in a table.
You read past the end of file with the UTL_FILE package.
TOO_MANY_ROWS  ORA-01422  You tried to execute a SELECT INTO statement and more than one row was returned.
ZERO_DIVIDE  ORA-01476  You tried to divide a number by zero.
INVALID_NUMBER  ORA-01722  You tried to execute an SQL statement that tried to convert a string to a number, but it was unsuccessful.
STORAGE_ERROR  ORA-06500  You ran out of memory or memory was corrupted.
PROGRAM_ERROR  ORA-06501  This is a generic "Contact Oracle support" message because an internal problem was encountered.
VALUE_ERROR  ORA-06502  You tried to perform an operation and there was a error on a conversion, truncation, or invalid constraining of numeric or character data.
CURSOR_ALREADY_OPEN  ORA-06511  You tried to open a cursor that is already open. 以上的例子中有关于命名的异常的使用方法。这里不再说了。
BEGIN 
  Execution section
EXCEPTION 
WHEN NO_DATA_FOUND THEN 
 dbms_output.put_line ('A SELECT...INTO did not return any row.'); 
 END; 
 
b:未命名系统异常:
这些系统异常没有名字,这些异常不经常出现,这些异常有错误代码和关联信息。
有两种方式处理未命名的异常:
        方法一: 使用WHEN OTHERS 异常处理
        方法二:给一个异常 关联异常代码和名称 ,然后像命名异常一样使用它。
方法一异常没有目标性,下面说明方法二:
使用Pragma 调用 EXCEPTION_INIT关联一个预定义的oracle错误号到程序定义的异常
下面是个demo:
DECLARE 
   exception_name EXCEPTION; 
   PRAGMA 
   EXCEPTION_INIT (exception_name, Err_code); 
BEGIN 
Execution section
EXCEPTION
  WHEN exception_name THEN
     handle the exception
END;
先声明异常名称,然后调用EXCEPTION_INIT函数绑定错误号码和异常名称, 绑定后这个异常名称就可以像命名式异常那样用了。
例如:
[sql] 
SQL> DECLARE  
  2         e_insert_excep  EXCEPTION;  --定义异常名称  
  3         PRAGMA EXCEPTION_INIT(e_insert_excep,-01400);   -- 关联异常名称和异  
常号  
  4         BEGIN  
  5         INSERT INTO departments (department_id,department_name) VALUES(280,N  
ULL);  
  6         EXCEPTION  
  7          WHEN  e_insert_excep THEN  
  8            DBMS_OUTPUT.PUT_LINE('INSERT OPERATION FAILED');  
  9            DBMS_OUTPUT.PUT_LINE(SQLERRM);  
 10         END;  
 11  /  
INSERT OPERATION FAILED  
ORA-01400: 无法将 NULL 插入 ("HR"."DEPARTMENTS"."DEPARTMENT_NAME")  
  
PL/SQL 过程已成功完成。  
 
首先定义一个 e_insert_excep异常名称, 然后调用 EXCEPTION_INIT函数绑定这个异常名称,最后出现异常输出错误信息。
SQLERRM的信息如下: ORA-01400: 无法将 NULL 插入 ("HR"."DEPARTMENTS"."DEPARTMENT_NAME")
 
 
需要关联 数字和自定义的错误名称;
两个变量: SQLCODE  错误代码
            SQLERRM  错误内容
   当抛出异常的时候,这两个变量会被自动填充,可以获取这两个的值来判断
   错误:         
 
3:用户自定义异常:
先看三个例子再解释:
ex1:
[sql] 
SQL>  DECLARE  
  2       v_deptno NUMBER := 500;  
  3       v_name  VARCHAR2(20)  :='Testing';  
  4       e_invalid_department EXCEPTION;  
  5    BEGIN  
  6       UPDATE departments SET department_name = v_name  
  7       WHERE  department_id = v_deptno;  
  8  
  9       IF SQL%NOTFOUND THEN  
 10          RAISE  e_invalid_department;  
 11       END IF;  
 12       COMMIT;  
 13     EXCEPTION  
 14       WHEN e_invalid_department THEN  
 15        DBMS_OUTPUT.PUT_LINE('No such department id');  
 16    END;  
 17  /  
No such department id  
  
PL/SQL 过程已成功完成。  
 
关于RAISE_APPLICATION_ERROR  过程;
语法:
raise_application_error(error_number,message[,{TRUE|FALSE}]);
可以通过这个过程定义一个自己的异常号和 异常信息
注意: error_number是介于: -20000..-20999的数字,message是一个
字符串最大长度为2k
[sql] 
SQL> DECLARE  
  2      v_deptno NUMBER := 500;  
  3      v_name VARCHAR2(20) := 'Testing';  
  4      e_invalid_department EXCEPTION;  --定义一个异常  
  5      PRAGMA  EXCEPTION_INIT(e_invalid_department,-20188);    --把异常和异常  
号绑定;  
  6  BEGIN  
  7      UPDATE  departments  
  8      SET  department_name =v_name  
  9      WHERE department_id = v_deptno;  
 10  
 11      IF SQL%NOTFOUND THEN  
 12  
 13         RAISE_APPLICATION_ERROR(-20188,'I write my error message here !');  
  
 14     END IF;  
 15     COMMIT;  
 16   EXCEPTION  
 17          WHEN  e_invalid_department THEN  
 18               DBMS_OUTPUT.PUT_LINE(SQLCODE || '--->' || SQLERRM);  
 19  END;  
 20  
 21  /  
-20188--->ORA-20188: I write my error message here !  
  
PL/SQL 过程已成功完成。  
说明:RAISE_APPLICATION_ERROR ( )
RAISE_APPLICATION_ERROR是一个内建的存储过程,这个存储过程可以显示用户
自定义的错误信息和错误号 ,这些错误号是Oracle开放出来供开发者用的,
范围为:-20000 and -20999
当使用RAISE_APPLICATION_ERROR的时候,所以以前的事务不提交,自动回滚。
语法格式如下:
RAISE_APPLICATION_ERROR (error_number, error_message); 
使用RAISE_APPLICATION_ERROR步骤如下:
 
1:首先在Declaration区域自定义一个exception,
2:在特定的逻辑规则下出现 Raise 用户自定义的exception
3:最后 catch 这个异常,在捕获后使用RAISE_APPLICATION_ERROR这个过程链接
自定义的错误号和错误信息。
 
重点: 关于异常的传播机制:
比较以下三个例子就会明白异常的传播机制:
ex1:
[sql] 
CREATE OR REPLACE PROCEDURE add_more_departments(p_name1 VARCHAR2, p_mgr1 NUMBER, p_loc1 NUMBER,p_name2 VARCHAR2, p_mgr2 NUMBER, p_loc2 NUMBER) IS  
BEGIN  
  INSERT INTO departments(department_id,department_name,manager_id,location_id)VALUES(departments_seq.NEXTVAL,p_name1,p_mgr1,p_loc1);  
  DBMS_OUTPUT.PUT_LINE('Add Dept: ' || p_name1);  
   
 INSERT INTO departments(department_id,department_name,manager_id,location_id)VALUES(departments_seq.NEXTVAL,p_name2,p_mgr2,p_loc2);  
 DBMS_OUTPUT.PUT_LINE('Add Dept: ' || p_name2);  
  
EXCEPTION   
      WHEN OTHERS THEN  
         DBMS_OUTPUT.PUT_LINE('Err: adding dept:');  
END;  
/          
  
CREATE OR REPLACE PROCEDURE create_more_departments  
IS  
BEGIN  
  add_more_departments('Media',100,1800,'Editing',99,1800);  
END;  
/  
  
BEGIN  
create_more_departments;  
END;   
 
这个例子中 99这条记录在表中本来就有,现在再次进行插入,会冲突报错
执行结果:以上两个insert 只有第一个插入进去了,第二个插入失败。
执行结果如下:
SQL> /
Add Dept: Media
Err: adding dept:
PL/SQL 过程已成功完成。
 
 
DEPARTMENT_ID DEPARTMENT_NAME
------------- ------------------------------
          230 IT Helpdesk
          240 Government Sales
          250 Retail Sales
          260 Recruiting
          270 Payroll
          340 Media
 
 
已选择28行。
只有第一条被插入
ex2:
在做第二个例子前先把上次的实验结果删除掉:
delete from departments where department_id >270;
select department_id,department_name from departments order by 1;
 
[sql] 
CREATE OR REPLACE PROCEDURE add_more_departments(p_name1 VARCHAR2, p_mgr1 NUMBER, p_loc1 NUMBER,p_name2 VARCHAR2, p_mgr2 NUMBER, p_loc2 NUMBER) IS  
BEGIN  
  INSERT INTO departments(department_id,department_name,manager_id,location_id)VALUES(departments_seq.NEXTVAL,p_name1,p_mgr1,p_loc1);  
  DBMS_OUTPUT.PUT_LINE('Add Dept: ' || p_name1);  
   
 INSERT INTO departments(department_id,department_name,manager_id,location_id)VALUES(departments_seq.NEXTVAL,p_name2,p_mgr2,p_loc2);  
 DBMS_OUTPUT.PUT_LINE('Add Dept: ' || p_name2);  
  
END;  
/          
  
CREATE OR REPLACE PROCEDURE create_more_departments  
IS  
BEGIN  
  add_more_departments('Media',100,1800,'Editing',99,1800);  
END;  
/   
  
BEGIN  
create_more_departments;  
END;   
 
执行结果如下:
SQL> BEGIN
  2  create_more_departments;
  3  END;
  4  /
Add Dept: Media
BEGIN
*
第 1 行出现错误:
ORA-02291: 违反完整约束条件 (HR.DEPT_MGR_FK) - 未找到父项关键字
ORA-06512: 在 "HR.ADD_MORE_DEPARTMENTS", line 6
ORA-06512: 在 "HR.CREATE_MORE_DEPARTMENTS", line 4
ORA-06512: 在 line 2
 
查询结果:
 
 
DEPARTMENT_ID DEPARTMENT_NAME
------------- ------------------------------
          230 IT Helpdesk
          240 Government Sales
          250 Retail Sales
          260 Recruiting
          270 Payroll
这次没有异常处理,把异常处理去掉了。
这次的执行结果: 两条记录一条记录也没有插入进去。 
ex3:
delete from departments where department_id >270;
select department_id,department_name from departments order by 1;
 
[sql] 
CREATE OR REPLACE PROCEDURE add_more_departments(p_name1 VARCHAR2, p_mgr1 NUMBER, p_loc1 NUMBER,p_name2 VARCHAR2, p_mgr2 NUMBER, p_loc2 NUMBER) IS  
BEGIN  
  INSERT INTO departments(department_id,department_name,manager_id,location_id)VALUES(departments_seq.NEXTVAL,p_name1,p_mgr1,p_loc1);  
  DBMS_OUTPUT.PUT_LINE('Add Dept: ' || p_name1);  
   
 INSERT INTO departments(department_id,department_name,manager_id,location_id)VALUES(departments_seq.NEXTVAL,p_name2,p_mgr2,p_loc2);  
 DBMS_OUTPUT.PUT_LINE('Add Dept: ' || p_name2);  
  
END;  
/          
  
CREATE OR REPLACE PROCEDURE create_more_departments  
IS  
BEGIN  
  add_more_departments('Media',100,1800,'Editing',99,1800);  
EXCEPTION   
      WHEN OTHERS THEN  
         DBMS_OUTPUT.PUT_LINE('Errors have happend');    
END;  
/   
BEGIN  
create_more_departments;  
END;   
 
执行结果:
SQL> BEGIN
  2  create_more_departments;
  3  END;
  4  /
Add Dept: Media
Errors have happend
 
PL/SQL 过程已成功完成。
查询结果:
DEPARTMENT_ID DEPARTMENT_NAME
------------- ------------------------------
          230 IT Helpdesk
          240 Government Sales
          250 Retail Sales
          260 Recruiting
          270 Payroll
          400 Media
 
这次把异常处理放在了最外面:调用的最外面:
执行结果如下:
执行成功的第一条语句被成功插入,第二条被捕获。

PL/SQL异常处理方法的更多相关文章

  1. Oracle数据库之PL/SQL异常处理

    Oracle数据库之PL/SQL异常处理 异常指的是在程序运行过程中发生的异常事件,通常是由硬件问题或者程序设计问题所导致的. PL/SQL程序设计过程中,即使是写得最好的程序也可能会遇到错误或未预料 ...

  2. PL/SQL异常处理

    As we all known,程序的错误一般分为两类:编译错误和运行时错误.其中运行时错误被称为异常.PL/SQL语句块中处理异常的部分即为异常处理部分.在异常处理部分,可以指定当特定异常发生时所采 ...

  3. ORACLE PL/SQL异常处理(Exception)学习笔记

    1.PL/SQL错误类型 错误类型 报告者 处理方法 编译时错误 PL/SQL编译器 交互式地处理:编译器报告错误,你必须更正这些错误 运行时错误 PL/SQL运行时引擎 程序化地处理:异常由异常处理 ...

  4. 【实战经验】64位Win7安装+32位Oracle + PL/SQL 解决方法

    软件环境:64位win7.32位Oracle 10g. PL/SQL 9.0.4.1644 前言:以前开发用的都是32位系统,突然换到64位上,安装环境真的有点麻烦了,尤其对于PL/SQL只支持32位 ...

  5. PL/SQL 异常处理

    SQL> set serveroutput on SQL> declare   name varchar2(10); begin   select ename into name from ...

  6. 64位Win7安装+32位Oracle + PL/SQL 解决方法

    软件景象:64位win7.32位Oracle 10g. PL/SQL 9.0.4.1644 媒介:以前开辟用的都是32位体系,忽然换到64位上,安装景象真的有点麻烦了,尤其对于PL/SQL只支撑32位 ...

  7. oracle ebs 采购订单关闭之PL/SQL实现方法

    应客户需求,需要写个脚本,批量关闭Bonus Item类型的采购订单,在metalink上搜索到一些方法,但是都测试不通.原来需要将代码生成一个并发程序.下面是测试成功的代码. 1.首先创建一个存储过 ...

  8. Oracle笔记 七、PL/SQL 异常处理

    --异常处理 declare sNum number := 0; begin sNum := 5 / sNum; dbms_output.put_line(sNum); exception when ...

  9. Oracle PL/SQL 异常处理

    Oracle数据库中的异常:没有异常的转移,因为没有受检异常和非受检异常得区分. 1.异常的产生: 2.异常的处理: declare --变量定义,初始化赋值. begin --变量的赋值,函数调用, ...

随机推荐

  1. swift 2.2 语法 (中)

    前言: 1.此文中的语法会根据Swift的升级变动而更新. 2.如果需要请移步 -> swift2.2 语法(上).swift 2.2语法(下) 函数 和C语言一样,swift也有函数,性质和我 ...

  2. warning 当xcode里点运行出现treating unicode character as whites

    可能是由于粘贴网页上的代码的时候两行之间的回车引起的,两行之间重新输入回车就行......删掉重新写一遍就ok了

  3. android中实现跑马灯效果以及AutoCompleteTestView与MultiAutoCompleteTextView的学习

    跑马灯效果 1.用过属性的方式实现跑马灯效果 属性:                  android:singleLine="true" 这个属性是设置TextView文本中文字 ...

  4. Python语法基础

    # coding=utf-8import random teacher = (1 < 3) and (2 > 5)print (teacher) index = random.randin ...

  5. [读书笔记] Head First 设计模式

    OO基础 抽象 封装 多态 继承 OO原则 原则 描述 封装变化 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混合在一起. 把会变化的部分取出来并“封装”起来,好让其他部分不 ...

  6. iOS 学习 - 10下载(1) NSURLConnection 篇

    程序的实现需要借助几个对象: NSURLRequest:建立了一个请求,可以指定缓存策略.超时时间.和NSURLRequest对应的还有一个NSMutableURLRequest,如果请求定义为NSM ...

  7. 列式存储(三)JFinal DB.tx()事务

    上一篇中说道了列式存储中新增表单时后台接收数据问题,在存入数据库时一次插入多条数据,就要用到事务. JFinal中有个封装好的事务应用,用起来非常方便简单. 写法1: Db.tx(new IAtom( ...

  8. 学习 HTML5-目录

    1.学习 HTML5-页面结构 2.HTML5标记 3.HTML5机构化语义元素 4.HTML5表单 5.HTML5媒体元素:Audio和Video 6.HTML5绘图API 7.HTML5 Canv ...

  9. ksvcreate: Process(m000) creation failed

    一测试服务器数据库(Oracle Database 10g Release 10.2.0.5.0 - 64bit Production)突然访问不了,检查发现数据库处于挂起模式(hang mode), ...

  10. JavaScript(一)——简介(简单介绍)

    1.JavaScript是个什么东西? 它是个脚本语言,需要有宿主文件,它的宿主文件是HTML文件. 2.它与Java什么关系? 没有什么直接的联系,Java是Sun公司(已被Oracle收购了),J ...