什么是异常?
在PL/SQL中的一个标识。
在程序运行期间被触发的错误。
异常是怎样被触发的?
产生一个Oracle错误。
用户显示触发。
怎样处理异常?
用异常处理句柄捕获异常。
传播异常到调用环境。

捕获异常

EXCEPTION
  WHEN exception1 [OR exception2 . . .] THEN
    statement1;
    statement2;
    . . .
  [WHEN exception3 [OR exception4 . . .] THEN
    statement1;
    statement2;
    . . .]
  [WHEN OTHERS THEN
    statement1;
    statement2;
    . . .]
异常捕获规则

WHEN OTHERS用于捕获所有未指定错误。必须是最后一个错误处理语句。
EXCEPTION关键字,标识异常处理的开始区域。
允许有多个异常处理子句。
在离开异常处理程序块之前,只能有一个错误处理子句被执行。
捕获Oracle服务器预定义错误

CASE_NOT_FOUND  (ORA-06592)
NO_DATA_FOUND  (ORA-1403)
TOO_MANY_ROWS  (ORA-1422)
DUP_VAL_ON_INDEX     (ORA-0001)
ZERO_DIVIDE (ORA-1476)
INVALID_CURSOR  (ORA-1001)
VALUE_ERROR (ORA-6502)
语法:

BEGIN  SELECT ... COMMIT;
EXCEPTION
  WHEN NO_DATA_FOUND THEN
    statement1;
    statement2;                                  
  WHEN TOO_MANY_ROWS THEN
    statement1;
  WHEN OTHERS THEN
    statement1;
    statement2;
    statement3;
END;    
实例

DECLARE
  v_empRecord  emp%ROWTYPE;
  v_empNo      emp.empno%TYPE;
BEGIN  
  SELECT *  INTO v_empRecord  FROM emp;
  --SELECT *  INTO v_empRecord  FROM emp  WHERE empno = 12345;
  --SELECT ename  INTO v_empNo  FROM emp  WHERE empno = 7369;
  EXCEPTION
    WHEN TOO_MANY_ROWS THEN
      dbms_output.put_line('TOO_MANY_ROWS EXCEPTION');
    WHEN NO_DATA_FOUND THEN
      dbms_output.put_line('NO_DATA_FOUND EXCEPTION');
    WHEN OTHERS THEN
      dbms_output.put_line('OTHERS EXCEPTION');
END;

捕获Oracle服务器错误
将数字-2292与e_products_invalid相关联。(-2292表示违反了完整性约束)
DECLARE
  e_products_invalid    EXCEPTION;
  PRAGMA EXCEPTION_INIT (
        e_products_invalid, -2292);
  v_message VARCHAR2(50);
BEGIN    
. . .
EXCEPTION
  WHEN e_products_invalid THEN
    :g_message := 'Product code
        specified is not valid.';
. . .
END;
example
为emp表创建一个能完成插入功能的存储过程insert_emp。
CREATE OR REPLACE PROCEDURE insert_emp
(no IN emp.empno%TYPE,   name IN emp.ename%TYPE DEFAULT NULL,
job IN emp.job%TYPE DEFAULT 'SALESMAN',
mgr IN emp.mgr%TYPE DEFAULT 7369,
hiredate emp.hiredate%TYPE DEFAULT SYSDATE,
salary emp.sal%TYPE DEFAULT 800,
comm emp.comm%TYPE DEFAULT NULL,
deptno emp.deptno%TYPE DEFAULT 10
)IS
e_integrity EXCEPTION;
PRAGMA EXCEPTION_INIT (e_integrity,-2291);
BEGIN
     INSERT INTO emp VALUES(no,name,job,mgr,hiredate,salary,comm,deptno);
EXCEPTION
    WHEN DUP_VAL_ON_INDEX THEN
        dbms_output.put_line('该员工已经存在!');
    WHEN e_integrity THEN
        dbms_output.put_line('部门编号填写错误!');
END;


example 向emp表中插入一条新记录,在执行的过程中捕获系统预定义异常、系统非预定义异常、用户自定义异常,并分别作相应的处理。
DECLARE  
  ex_null EXCEPTION; --系统非预定义异常的定义和关联
  PRAGMA EXCEPTION_INIT(ex_null,-01400);  
  ex_insert EXCEPTION; --用户自定义异常的定义  
  eno scott.emp.empno%TYPE:=&no; --定义程序块变量
  e_sal scott.emp.sal%TYPE:=&salary;
BEGIN
  IF e_sal>10000 THEN
    RAISE ex_insert;  --用户自定义异常的触发
  ELSE
    INSERT INTO scott.emp(empno,sal) VALUES(eno,e_sal);
  END IF;
  EXCEPTION
    WHEN DUP_VAL_ON_INDEX  THEN   --系统预定义异常的捕获和处理
      dbms_output.put_line('该员工已经存在!');
    WHEN ex_null THEN   --系统非预定义异常的捕获和处理
      dbms_output.put_line('职工编号不能为空!');
    WHEN ex_insert THEN   --用户自定义异常的捕获和处理
      dbms_output.put_line('员工的工资不能超过10000!');
END;


捕获异常中的函数
 SQLCODE
返回错误代码。
SQLERRM
返回与错误代码相关联的消息。
DECLARE
  v_error_code      NUMBER;
  v_error_message   VARCHAR2(255);
BEGIN
...
EXCEPTION
...
  WHEN OTHERS THEN
    ROLLBACK;
    v_error_code := SQLCODE ;
    v_error_message := SQLERRM ;
    INSERT INTO errors VALUES(v_error_code,
                   v_error_message);
END;


RAISE_APPLICATION_ERROR

raise_application_error (error_number,
        message[, {TRUE | FALSE}]);    
从存储过程中触发用户自定义异常。

...
     EXCEPTION
        WHEN NO_DATA_FOUND THEN
             RAISE_APPLICATION_ERROR (-20201,'Manager is not a valid employee.');
     END;
    
例8.4  为scott.emp表创建一个能完成插入功能的存储过程insert_emp。
CREATE OR REPLACE PROCEDURE insert_emp
(no IN scott.emp.empno%TYPE,
name IN scott.emp.ename%TYPE DEFAULT NULL,
job IN scott.emp.job%TYPE DEFAULT 'SALESMAN',
mgr IN scott.emp.mgr%TYPE DEFAULT 7369,
hiredate scott.emp.hiredate%TYPE DEFAULT SYSDATE,
salary scott.emp.sal%TYPE DEFAULT 800,
comm scott.emp.comm%TYPE DEFAULT NULL,
deptno scott.emp.deptno%TYPE DEFAULT 10
)
IS
e_integrity EXCEPTION;
PRAGMA EXCEPTION_INIT (e_integrity,-2291);
BEGIN
INSERT INTO scott.emp VALUES(no,name,job,mgr,hiredate,salary,comm,deptno);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
dbms_output.put_line('该员工已经存在!');
WHEN e_integrity THEN
dbms_output.put_line('部门编号填写错误!');
END;

oracle PL/SQL(procedure language/SQL)程序设计之异常(exception)的更多相关文章

  1. oracle PL/SQL(procedure language/SQL)程序设计

    PL/SQL(procedure language/SQL)语言是Oracle对SQL语言的过程化扩充,是一个完整的编程语言.PL/SQL实现了过程化语句(如分支.循环等)与SQL语句的无缝连接,将过 ...

  2. Oracle笔记--PL/SQL(Procedure Language & Structured Query Language)

    1.PL/SQL是一种高级数据库程序设计语言,专门用于在各种环境下对Oracle数据库进行访问.该语言集成于数据库服务器中,所以PL/SQL代码可以对数据进行快速高效的处理. 2.PL/SQL是对SQ ...

  3. oracle PL/SQL(procedure language/SQL)程序设计之函数+过程+包

    匿名PL/SQL块回顾 DECLARE (可选)    定义在PL/SQL块中要使用的对象BEGIN (必须)    执行语句EXCEPTION (可选)    错误处理语句END; (必须)匿名块( ...

  4. oracle PL/SQL(procedure language/SQL)程序设计之函数+过程+包(转)

    匿名PL/SQL块回顾 DECLARE (可选)     定义在PL/SQL块中要使用的对象 BEGIN (必须)     执行语句 EXCEPTION (可选)     错误处理语句 END; (必 ...

  5. oracle PL/SQL(procedure language/SQL)程序设计之游标cursors

    游标 Cursors--Conception 每一条被Oracle服务器执行的SQL语句都有一个独立的游标与之相关联:隐式游标 Implicit cursors: 用于所有的DML和PL/SQL的SE ...

  6. oracle PL/SQL(procedure language/SQL)程序设计之触发器(trigger)

    创建触发器 触发器类似于过程和函数,都拥有声明.执行和异常处理过程的带名PL/SQL块.与包类似,触发器必须存储在数据库中.前面已经讲过,过程是显式地通过过程调用执行的,同时过程调用可以传递参数.与之 ...

  7. oracle PL/SQL(procedure language/SQL)程序设计(在PL/SQL中使用SQL)

    在PL/SQL程序中,允许使用的SQL语句只有DML和事务控制语句,使用DDL语句是非法的.使用SELECT语句从数据库中选取数据时,只能返回一行数据.使用COMMIT,  ROLLBACK, 和SA ...

  8. oracle PL/SQL(procedure language/SQL)程序设计--控制结构(if else )

    IF逻辑结构:IF-THEN-END IFIF-THEN-ELSE-END IFIF-THEN-ELSIF-END IF 语法 IF condition THEN  statements;[ELSIF ...

  9. oracle PL/SQL(procedure language/SQL)程序设计(续集)之PL/SQL函数

    PL/SQL函数 examples:“ 构造一个邮件地址 v_mailing_address := v_name||CHR(10)||                                 ...

随机推荐

  1. Linux下查看文件和文件夹大小的df和du命令

        转自:http://www.yayu.org/look.php?id=162 当磁盘大小超过标准时会有报警提示,这时如果掌握df和du命令是非常明智的选择. df可以查看一级文件夹大小.使用比 ...

  2. mvc中ajax.beginform一次提交重复Post两次的问题解决

    在MVC4中使用ajax.beginform来做添加商品到购物车中的提交操作,结果点击提交按钮后,出现两次post,这样导致商品的数量增加了一倍. 原因:@Scripts.Render("~ ...

  3. 使用HTML5的十大原因

    你难道还没有考虑使用HTML5? 当然我猜想你可能有自己的原因:它现在还没有被广泛的支持,在IE中不好使,或者你就是喜欢写比较严格的XHTML代码.HTML5是web开发世界的一次重大的改变,事实上不 ...

  4. Ubuntu ENet 的下载和编译

    ENet的目的是提供一个相对轻便.简单和强大的网络通信层的UDP(用户数据报协议). 它提供的主要功能是可选的.可靠的.顺序的数据包发送. ENet省略了一些更高层次的网络功能,如身份验证.加密,尤其 ...

  5. HttpRuntime.Cache 失效

    最近做一个报纸内容类网站,为了提高响应速度,将首页各栏目以及二级栏目中Part文献列表存储在HttpRuntime.Cache缓存中,发布后发现问题,刚插入的缓存很快就失效,本机调试没有问题. 由于H ...

  6. 凯尔卡C68全球版汽车电脑诊断仪

    产品简介: C68汽车故障诊断仪是凯尔卡公司新推出的一款集经济.简约.稳定.耐用于一体的汽车诊断设备, 该产品采用了最新的智能移植技术,集成度高:C68车型覆盖广,测试功能强大.数据准确等优点, 是目 ...

  7. Spark MLlib Deep Learning Convolution Neural Network (深度学习-卷积神经网络)3.1

    3.Spark MLlib Deep Learning Convolution Neural Network (深度学习-卷积神经网络)3.1 http://blog.csdn.net/sunbow0 ...

  8. Visual Studio 2015 和 Apache Cordova

    英文原版:http://www.codeproject.com/Articles/860150/Visual-Studio-and-Apache-Cordova 在开始前,问一下自己下面这些问题: 熟 ...

  9. codeforces Gym 100187B B. A Lot of Joy

    B. A Lot of Joy Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100187/proble ...

  10. 你应该知道的c# 反射详解

    C#反射 首先了解C#反射的概念,反射是一个运行库类型发现的过程.通过反射可以得到一个给定程序集所包含的所有类型的列表, 这个列表包括给定类型中定义的方法.字段.属性和事件.也可以动态的发现一组给定类 ...