PL SQL异常处理

PL/SQL程序执行过程中出现的错误,称之为异常。


PL/SQL程序的错误可分为两类:
    一类是PL/SQL语法错误,它由PL/SQL编译器发现并给出错误信息,
    另一类是运行时错误,由PL/SQL运行时引擎发现并给出错误信息。


异常分类:
    PL/SQL语言的异常分为两大类
一类是ORACLE系统异常
ORACLE系统异常又分为两种,一种是预定义异常,另一种是非预定义异常。
    另一类是自定义异常


    (1)预定义异常
预定义异常是ORACLE系统异常中的一种,用于处理常见的ORACLE错误。ORACLE预定义异常的特点是,
ORACLE系统定义了它们的错误编号与异常名字。当运行PL/SQL代码产生预定义错误时,与错误对应的
预定义异常被自动抛出,通过预定义异常名字捕获该异常。
预定义异常与ORACLE错误编号之间的对应关系如下所示:

预定义异常   Oracle错误   错误代码  描述
  
ACCESS_INTO_NULL   ORA-06530   -6530  试图给一个没有初始化(为NULL)的对象赋值
 
CASE_NOT_FOUND     ORA-06592    -6592  在CASE语句中没有WHEN子句被选择,并且没
  有ELSE子句


COLLECTION_IS_NULL ORA-06531   -6531  试图将EXISTS以外的集合(collection)方法
 应用到一个没有被初始化(为NULL)的嵌套表
(nested table)和变长数组(varray)中,
 或者试图给没有初始化的嵌套表
(nested table)或变长数组()varray中的
 元素赋值


CURSOR_ALREADY_OPEN ORA-06511   -6511  试图打开一个已经打开的游标,一个游标在它
 重新打开前必须被关闭。一个游标FOR循环会
 自动地打开所涉及的游标,所以在游标循环里
 不能打开游标


DUL_VAL_ON_INDEX   ORA-00001   -1   试图在一个有惟一性约束的数据库列中存储重复的值


  INVALID_CURSOR   ORA-01001   -1001  试图执行一个无效的游标操作  


INVALID_NUMBER   ORA-01722   -1722  试图将一个看起来不像是一个有效的数字的字
 符串转换成数字失败时,而在过程性语句中,
 将会引发VALUE_ERROR错误,代替
 INVALID_NUMBER错误


LOGIN_DENIED   ORA-01017   -1017  用一个无效的用户名或口令去登陆Oracle


NO_DATA_FOUND   ORA-01403   100  一个SELECT INTO语句没有返回数据或者程序
 引用一个嵌套表中被删除的元素或索引表中一
 个没有被初始化的元素  

NOT_LOGGED_ON   ORA-01012   -1012  发布一个数据库呼叫指令而没有连接到数据库 


PROGRAM_ERROR   ORA-06501   -6501  Oracle内在错误,通常是由PL/SQL本身造成
 的,这种情况下应该通知Oracle公司技术部门 


ROWTYPE_MISMATCH   ORA-06504   -6504  宿主游标变量和PL/SQL游标变量相关的作业有
 着不兼容的类型 


SELF_IF_NULL   ORA-30625   -30625  程序试图调用一个空的实例的成员方法


STORAGE_ERROR ORA-06500 -6500  PL/SQL运行时内存不够或者内存是有问题的 

SUBSCRIPT_BEYOND_COUNT  ORA-06533  -6533  引用一个嵌套表(nested table)或变长数
 组(varray)的元素时索引值大于集合中元素
 的数量 


SUBSCRIPT_OUTSIDE_LIMIT  ORA-06532 -6532  引用一个嵌套表(nested table)或变长数
 组(varray)的元素时使用的索引值(例如
 -1)超出了规定的范围 


SYS_INVALID_ROWID   ORA-01410   -1410  试图将一个看起来不像是一个有效的ROWID的字
 符串转换成一个ROWID时  


TIMEOUT_ON_RESOURCE  ORA-00051   -51  Oracle在等待资源时发生超时现象  


TOO_MANY_ROWS ORA-01422 -1422  SELECT INTO语句返回了多行数据


VALUE_ERROR   ORA-06502   -6502  一个算法、转换、截断或者大小约束错误发生,
 如果在SQL语句中发生错误则会引发
INVALID_ERROR错误,替代了VALUE_ERROR错误 


  ZERO_DIVIDE   ORA-01476   -1476  发生被零除 


    (2)非预定义异常
也是ORACLE系统异常中的一种,用于处理预定义以外的ORACLE系统错误。ORACLE非预定义异常的特点
是,ORACLE系统定义了它们的错误编号,但没有定义异常名字。这些ORACLE系统错误没有预定义异
常(异常名字)与其关联,需要在PL/SQL块的声明部分定义一个异常名字,然后通过伪过程
PRAGMA EXCEPTION_INIT 将该异常名字与一个ORACLE 错误编号相关联。这样,当运行PL/SQL代码
产生非预定义错误时,与错误代码对应的非预定义异常被自动抛出,通过定义的异常名字捕获该异常,
并对错误进行处理。


    (3)自定义异常
自定义异常用于处理用户定义错误,即处理与ORACLE系统错误无关的其错误。自定义异常是指有些操
作不会产生ORACLE系统错误,但是程序员从业务规则角度考虑,认为是一种错误。例如,执行UPDATE
操作没有更新任何记录行时,不会引发ORACLE系统错误,也不会发生异常。但是,有时需要开发人员
为此操作产生一个异常,以便进行处理,这就是用户定义异常。


异常处理
PL/SQL程序中,异常处理按以下3个步骤进行:
定义异常
抛出异常
捕获及处理异常


(1)定义异常
如前所述,ORACLE中的异常分为预定义异常、非预定义异常和自定义异常,其中预定义异常
由系统隐式定义,而后两种异常则需要用户定义。定义异常的方法是在PL/SQL程序的声明
部分定义一个EXCEPTION类型的变量,其格式为:


exception_name EXCEPTION; 


其中exception_name 为异常名,如果 是非预定义异常,还需要使用伪过程,在编译阶段将
异常名与一个ORACLE错误代码相关联,其语句格式为:

PRAGMA EXCEPTION_INIT(exception_name,error_number);


其中,exception_name为异常名,error_number为ORACLE系统内部错误号,用一个负位数
表示,-20999~-20000为用户定义错误的保留号。


(2)抛出异常
由于系统不能自动识别用户定义错误,因此当产生自定义错误时,需要程序员使用特定的PL/SQL
代码抛出相应的自定义异常。自定义异常的抛出语句格式为:


RAISE exception_name;

(3)捕获及处理异常
异常处理的基本格式为:

EXCEPTION
WHEN e_name1 [OR e_name2...] THEN
sequence of statements1;
WHEN e_name3 [OR e_name4...] THEN
sequence of statements2;
......
[WHEN OTHERS THEN
sequence of statementsn;]
END;


异常处理实例
处理预定义异常


   例1:
DECLARE
v_dividend NUMBER:=50;
v_divisor NUMBER:=0;
v_quotient NUMBER;
BEGIN
v_quotient:=v_dividend/v_divisor;
EXCEPTION
WHEN ZERO_DIVIDE THEN
DBMS_OUTPUT.PUT_LINE('divisor is 0');
END;
/


   例2:输入员工编号,如果员工不存在,则提示错误
SQL> SET SERVEROUTPUT ON


DECLARE
v_id emp.empno%TYPE;
v_name emp.ename%TYPE;
BEGIN
v_id:=&inputid;
select ename INTO v_name FROM emp WHERE empno=v_id;
DBMS_OUTPUT.PUT_LINE('EMPNO = '||v_name);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('NOT FOUND RECORD!');
END;
/


   例3:使用两种异常处理,避免找不到记录和找到多条记录而赋给一个变量的错误


DECLARE
v_job emp.job%TYPE;
v_name emp.ename%TYPE;
BEGIN
v_job:='&inputjob';
select ename INTO v_name FROM emp WHERE job=v_job;
DBMS_OUTPUT.PUT_LINE('EMPNO = '||v_name);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('NOT FOUND RECORD!');
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('FOUND RECORD TOO MANY!');
END;
/


非预定义异常
也是ORACLE系统异常中的一种,用于处理预定义以外的ORACLE系统错误。ORACLE非预定义异常的特点
是,ORACLE系统定义了它们的错误编号,但没有定义异常名字。这些ORACLE系统错误没有预定义异
常(异常名字)与其关联,需要在PL/SQL块的声明部分定义一个异常名字,然后通过伪过程
PRAGMA EXCEPTION_INIT 将该异常名字与一个ORACLE 错误编号相关联。这样,当运行PL/SQL代码
产生非预定义错误时,与错误代码对应的非预定义异常被自动抛出,通过定义的异常名字捕获该异常,
并对错误进行处理。
非预定义异常需要用户定义异常名,而且还要使用伪过程,在编译阶段将异常名与一个ORACLE
错误代码相关联。


   例1:在dept删除10号部门,试验引用完整性约束异常
SQL>    DECLARE
  2                     e_deptid EXCEPTION;
  3                     PRAGMA EXCEPTION_INIT(e_deptid,-2292);
  4             BEGIN
  5                     DELETE FROM DEPT WHERE DEPTNO=&e_deptid ;
  6             EXCEPTION
  7                     WHEN e_deptid THEN
  8                             DBMS_OUTPUT.PUT_LINE('at sub table have record!');
  9             END;
 10             /
输入 e_deptid 的值:  20
原值    5:                      DELETE FROM DEPT WHERE DEPTNO=&e_deptid ;
新值    5:                      DELETE FROM DEPT WHERE DEPTNO=20 ;
at sub table have records !


PL/SQL 过程已成功完成。


SQL>    DECLARE
  2                     e_deptid EXCEPTION;
  3                     PRAGMA EXCEPTION_INIT(e_deptid,-2292);
  4             BEGIN
  5                     DELETE FROM DEPT WHERE DEPTNO=&e_deptid ;
  6             EXCEPTION
  7                     WHEN e_deptid THEN
  8                             DBMS_OUTPUT.PUT_LINE('at sub table have record!');
  9             END;
 10             /
输入 e_deptid 的值:  40
原值    5:                      DELETE FROM DEPT WHERE DEPTNO=&e_deptid ;
新值    5:                      DELETE FROM DEPT WHERE DEPTNO=40 ;


PL/SQL 过程已成功完成。


   例2:在emp表中插入记录,部门号为80,试验参照完整性约束异常


DECLARE
e_deptid EXCEPTION;
PRAGMA EXCEPTION_INIT(e_deptid,-2291);
BEGIN
INSERT INTO EMP (EMPNO,DEPTNO) VALUES (8001,80); 
EXCEPTION
WHEN e_deptid THEN
DBMS_OUTPUT.PUT_LINE('deptno 80 at table dept no exist !');
END;
/


deptno 80 at table dept no exist !


PL/SQL 过程已成功完成。


   例3:在emp表中插入一条EMPNO存在的记录


DECLARE
e_deptid EXCEPTION;
PRAGMA EXCEPTION_INIT(e_deptid,-0001);
BEGIN
INSERT INTO EMP (EMPNO,DEPTNO) VALUES (7788,10); 
EXCEPTION
WHEN e_deptid THEN
DBMS_OUTPUT.PUT_LINE('record is exist !');
END;
/


SQL> select empno,deptno from emp where empno=7788;


     EMPNO     DEPTNO
---------- ----------
      7788         10


自定义异常处理
自定义异常不仅需要用户定义异常名字,还要程序员安排何时抛出异常及对异常的处理。


   例1:在emp中插入一条工资为负数的记录。


DECLARE
e_sal EXCEPTION;
v_sal emp.sal%TYPE;
BEGIN
v_sal:=&inputsal;
IF v_sal<0 THEN
RAISE e_sal;
END IF;
INSERT INTO emp(empno,ename,sal) values (8002,'TEST',v_sal);
EXCEPTION
WHEN e_sal THEN
DBMS_OUTPUT.PUT_LINE('sal not < 0 !');
END;
/


输入 inputsal 的值:  -1000
原值    5:                      v_sal:=&inputsal;
新值    5:                      v_sal:=-1000;
sal not < 0 !


PL/SQL 过程已成功完成。


   例2:带有WHEN OTHERS THEN的异常处理


DECLARE
e_sal EXCEPTION;
v_sal emp.sal%TYPE;
BEGIN
v_sal:=&inputsal;
INSERT INTO emp(empno,ename,sal) values (8002,'TEST',v_sal);
IF v_sal<0 THEN
RAISE e_sal;
END IF;
EXCEPTION
WHEN e_sal THEN
DBMS_OUTPUT.PUT_LINE('sal not < 0 !');
rollback;
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('other error !');
rollback;
END;
/


使用异常函数
在PL/SQL代码运行出现错误时,通过使用异常函数可以获得错误代码及相关的错误描述,
其中函数SQLCODE用于获得ORACLE错误代码,而SQLERRM则用于获得与之相应 的错误描述。


DECLARE
e_sal EXCEPTION;
v_sal emp.sal%TYPE;
v_empno emp.empno%TYPE;
v_deptno emp.deptno%TYPE;
BEGIN
v_sal:=&inputsal;
v_empno:=&inputempno;
v_deptno:=&inputdeptno;
INSERT INTO emp(empno,deptno,sal) values (v_empno,v_deptno,v_sal);
IF v_sal<0 THEN
RAISE e_sal;
END IF;
EXCEPTION
WHEN e_sal THEN
DBMS_OUTPUT.PUT_LINE('sal not < 0 !');
rollback;
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('error code:'||SQLCODE);
DBMS_OUTPUT.PUT_LINE('error desc:'||SQLERRM);
END;
/


第一种情况:
输入 inputsal 的值:     100
原值    7:              v_sal:=&inputsal;
新值    7:              v_sal:= 100;
输入 inputempno 的值:  100
原值    8:              v_empno:=&inputempno;
新值    8:              v_empno:=100;
输入 inputdeptno 的值:  10
原值    9:              v_deptno:=&inputdeptno;
新值    9:              v_deptno:=10;


PL/SQL 过程已成功完成。


第二种情况:
输入 inputsal 的值:     -1000
原值    7:              v_sal:=&inputsal;
新值    7:              v_sal:= -1000;
输入 inputempno 的值:  1000
原值    8:              v_empno:=&inputempno;
新值    8:              v_empno:=1000;
输入 inputdeptno 的值:  20
原值    9:              v_deptno:=&inputdeptno;
新值    9:              v_deptno:=20;
sal not < 0 !


PL/SQL 过程已成功完成。


























  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PL/SQL是用于数据库编程和管理的编程语言,它可以将Excel的数据导入到数据库表中。 首先,我们需要创建一个数据库表,该表的字段应该与Excel文件中的列相对应。例如,如果Excel文件中有姓名、年龄和地址等列,那么我们应该在数据库表中创建相应的字段。 接下来,我们可以使用PL/SQL来编写一个过程或函数,该过程或函数负责将Excel文件的数据导入到数据库表中。这可以通过使用PL/SQL的文件处理功能和SQL Loader技术来实现。 在过程或函数中,我们可以使用PL/SQL的语法和库函数来打开Excel文件、读取文件中的数据,并将数据逐行插入到数据库表中。这可以通过使用包括UTL_FILE、DBMS_LOB和其他文件处理包中的函数和过程来实现。 在导入数据之前,我们还需要确保Excel文件的格式正确,并且数据库表中的字段和数据类型与Excel文件的数据相匹配。否则,导入过程可能会失败,或者导入的数据可能会出现错误。 最后,在PL/SQL代码中,我们可以添加必要的错误处理语句和异常处理机制,以确保在遇到错误时能够进行适当的处理,并提供相应的错误信息。 当PL/SQL代码编写完成后,可以通过在数据库系统中执行该代码来导入Excel文件的数据到目标表中。 总而言之,使用PL/SQL可以很方便地将Excel文件的数据导入到数据库表中。通过编写适当的PL/SQL代码,我们可以打开、读取和插入Excel文件中的数据,从而实现数据的导入功能。这种方法可以有效地处理大量的数据,并提供良好的错误处理机制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值