PL/SQL中的例外(异常)处理:
例外处理是用来处理程序在正常执行过程中所出现未预料
的事件
由于设计问题,代码错误,硬件故障等许多其它原因都
会引起程序运行中的错误
虽然不能预测所有可能的错误,但
可以在程序中规划处理某些类型的错误
在PL/SQL程序块中一旦发生异常,就会终止该程序块执行
PL/SQL程序块中引入对异常进行处理,使程序在出错时可继
续运行
例外有两种:内部例外和用户定义例外
内部例外:
是运行系统预先定义的例外,如除数为零,内存不足,执行查询
语句未查询到数据等等
ZERO_DIVIDE 除以0引起的
STORAGE_ERROR 用完了内存或者内存存储破坏引起的
NO_DATA_FOUND 执行select into 语句时没有行返回或引用PL/SQL表中未初始化的行
TOO_MANY_ROWS PL/SQL中未使用游标,执行select into语句返回了多行数据引起
INVALID_CURSOR 执行一个非法的游标操作引起的,比如,关闭未打开的游标
DUP_VAI_ON_INDEX 在具有唯一索引约束的数据库系列上存储一个重复值而引起
CURSOR_ALREADY_OPEN 试图打开一个已经打开的图标
用户自定义的例外:
该例外必须要在说明部分定义, 给予命名
并用RAISE语句在
执行部分显式地引发该例外
若程序中给出例外处理,当一个
错误发生时,一个例外被引起,即正常的操作被停止,将流程控制
转移到程序的例外处理部分
对例外的处理过程是放在程序块的执行部分后面, 由关键字
EXCEPTION开始
在PL/SQL程序块中例外处理部分可处理
一个或多个例外, 例外处理放在例外处理部分的WHEN子句
之后。
例外处理部分程序格式
EXCEPTION
WHEN 例外名表1 THEN
语句序列1
WHEN 例外名表2 THEN
语句序列2
........
[WHEN OTHERS THEN
语句序列n ]
在每个WHEN之后,列出例外名表,例外名多于一个时,由OR关键字将多个例外名分开,
OTHERS例外处理是可选的,
在一个PL/SQL块或子程序的例处处理部分仅出现一次
对指定这些例外名的处理,可按任意次序排列,OTHERS例外处理必须排在最后
给出OTHERS例外处理,使程序保证了没有例外是未被处理
SQL> set serveroutput on
declare
x number ;
begin
x:=1/0;
dbms_output.put_line(‘works’);
exception
when value_error then
dbms_output.put_line(‘value error’);
when others then
dbms_output.put_line(‘other error’);
end;
用户定义的例外处理:
PL\SQL允许在程序中用户自己定义例外,称为用户定义例外
用户定义的例外必须要在程序块的说明部分进行说明
并在执
行部分用RAISE语句显示地引发例外
例外说明形式:
例外名 EXCEPTION;
例外说明和变量说明类似 , 但要注意其区别:
1.例外是一个出错条件, 不是一种对象, 与变量不同,例外名不能
出现在赋值语句和SQL语句中
2.在同一个块中一个例外名不能被说明两次, 但同一个例外名
可在不同块中被说明
3.例外说明在说明它的块中是局部的, 而对于它的所有子块来
说它是全局的。
4.在一子块中可引用局部或全局例外,而在包装
块中不能引用在子块中说明的例外
5.如果在子块中重新说明一个全局例外, 该局部说明占优势, 以致子块不能引用全局例外,
除非用块标号说明, 形式为:
块标号 · 例外名
DECLARE
salary_code varchar2(1) ;
invaliad_salary_code EXCEPTION;
BEGIN
salary_code:=’X’;
if salary_code NOT IN (‘A’,’B’,’C’) THEN
RAISE invaliad_salary_code;
end if;
dbms_output.put_line(‘ok’);
EXCEPTION
when invaliad_salary_code then
dbms_output.put_line(‘invaliad salary code’);
END;
对自定义的例外名在执行部分被语句RAISE触发。当触发了
例外后,执行就被传递给程序块的例外处理部分。
一旦自定义例外被触发, 为它所创建的异常处理器就被执行
查询EMP表中所有雇员工资,若发现大于¥10000者,说明出错并退出
DECLARE
v_sal_err emp.sal%TYPE:=10000;
CURSOR C1 IS
SELECT sal
FROM EMP;
v_sal emp.sal%TYPE;
sal_error EXCEPTION;
BEGIN
OPEN C1;
FETCH C1 INTO v_sal ;
LOOP
EXIT WHEN C1%NOTFOUND;
IF v_sal>10000
RAISE sal_error ;
ELSE
FETCH C1 INTO v_sal ;
END IF ;
END LOOP;
CLOSE C1;
EXCEPTION
WHEN NO_DATA_FOUND THEN
INSERT INTO TMP(message)
VALUSE(‘No found any empoloyee’);
CLOSE C1;
WHEN sal_error THEN / * 对用户定义的例外处理 */
INSERT INTO TMP(message)
VALUSE(‘found error : sal>10000’);
CLOSE C1;
WHEN OTHERS THEN
INSERT INTO TEMP(message)
VALUES (‘found other error’:);
CLOSE C1;
END ;
Raise_application_error过程
可以使用oracle提供的标准包dbms_standard中所定义重新定义异常错误消息,
这为应用提供了一种与oracle交互的方法
的raise_application_error过程,
使用的时候前面可以不加dbms_standard
过程raise_application_error的语法如下:
Raise_application_error(error_number,error_message,[keep_errors]);
其中
1.error_number:用户可自己定义,从-20000到-20999
2.error_message:是需要定义的相应提示信息,应小于2kb
3.keep_errors:可选项,如果为ture,则新错误添加到已经引发的错误列表,如为false,则新错误将替换当前错误列表。默认值为false
Declare
V_eno emp.empno%type:=1344;
No_found exception;
Begin
update emp set sal=sal*1.1
where empno=v_eno;
if sql%notfound then
raise no_found;
end if;
Exception
when no_found then
raise_application_error(-20001,‘the number doesnot exist’);
when others then
dbms_output.put_line(‘other errors’);
End;