异常处理

异常处理

希望程序继续执行

错误处理

错误处理部分位于异常的可执行部分之后,是由when语句引导多个分支构成语法如下

exception
  when 错误1 [or 错误2] then
  语句序列1;
  when 错误3[or 错误4] then
  语句序列2;
  when others then
  语句序列n;

错误是在标准包中由系统预定义的标准错误,或是由用户在程序说明部分自定义的错误。

凡是出现在when后面的错误都说可以捕捉的错误,其他未被捕捉的错误,将在when others部分进行统一处理,others必须是exception部分最后一个错误处理分支。如果要在该分支进一步进行判断错误种类,可以通过使用预定义函数sqlcode()和sqlerrm()来活动系统错误号和错误信息。

如果在程序子块中发生错误,但是子块没有错误处理部分,则错误将会传递到主程序中。

预定义错误

oracle系统错误很多,只有一部分常见错误在标准包中予以定义。定义错误在exception部分通过标准错误名来进行判定,并进行异常处理。常见预定义异常如下。

错误名称错误代码错误
CURSOR_ALREADY_OPEN ORA_06511 试图打开已经打开的游标
INVALID_CLUSOR ORA_01001 视图使用没有打开的游标
DUP_VAL_ON_INDEX ORA_00001 保存重复值到唯一索引约束的列中
ZERO_DIVIDE ORA_01476 发生除数为0的除法错误。
INVALID_NUMBER ORA_01722 视图对无效字符进数值转换
ROWTYPE_MISMATCH 0RA-06504 主变量和游标的类型不兼容
VALUE_ERROR ORA_06502 转换,截断或算术运算错误。
too_many_rows ORA_01422 SELECT ..INTO 语句返回多余一行的数据
no_data_found ORA_01403 SELECT ..INTO 语句没有数据返回
timeout_on_resource ora_00051 等待资源时发生超时错误。
transaction_backed_out ora_00060 由于死锁提交失败
storage_error ora_06500 发生内存错误
program_error ora_06501 发生pl/sql内部错误
not_logged_on ora_01012 视图操作未连接的数据库
login_dented ora_01017 在连接时提供了无效用户名或口令
定义错误

如果一个系统错误没有在标准包中定义,则需要在说明部分定义,定义后使用pragma exception_init来将一个定义错误同一个特别的oracle错误代码相关联,就i可以同系统预定义的错误一样,使用

语法如下

    错误名 EXCEPTION ;
PRAGMA EXCEPTION_INIT(错误名,错误代码);
--注意(9i中)PRAGMAEXCEPTION_INIT(错误名,错误代码);
--eg1
declare
  str varchar2(2000);
  to_manyvaluesss exception;
  pragma exception_init(to_manyvaluesss,-00913);
begin
  str:='insert into xujb_temp4 values(''23331'',''hj'')';
  execute immediate str;
  excepiton
      when to_manyvaluesss then
      dbms_output.putline('数据值过多'||sqlcode||','||sqlerrm);
      when others then
      dbms_output.putline('其他未知错误'||sqlcode||','||sqlerrm);
end;

 

自定义异常

程序设计者可以利用引发异常的机制来进行程序设计,自己定义异常类型,可以在声明部分定义新的异常类型,用户定义的错误不能由系统来触发,必须由程序员显示的触发

错误名  EXCEPTION;  -----定义异常

RAISE 错误名;       ------抛出异常,手动触发

RAISE 也可以用来引发模拟系统错误,比如,RAISE ZERO_DIVIDE将引发模拟除零错误。

使用RAISE_APPLICATION_ERROR函数也可以引发异常。该函数要传递两个参数,第一个是用户自定义错误编号,的哥是参数用户自定义的错误信息。使用该函数引发的异常的编号应该在20 000和20 999之间选择

自定义异常的处理方式同前

---eg1:

declare
  my_exception1 exception;
  my_exception2 exception;
  sale1 number default 8000;
  str varchar2(2000);
begin
   insert into xujb_temp1 values('7','王小儿',sale1);
  if sale1>6000 then
  rasie my_exception1;
  elsif sale1<1000 then
  raise my_exception2;
  end if;
  commit;
  dbms_output.put('数据录入成功');
  exception
      when my_exception1 then
      dbms_output.put('金额超限6000录入失败');
      rollback;
      when my_exception2 then
      dbms_output.put('金额低于下限1000录入失败');
      rollback;
      when others then
      dbms_output.put('其他异常'||sqlcode||','||sqlerrm);

end;

--eg2使用RAISE_APPLICATION_ERROR函数抛出异常并终止程序,类似系统报错

declare
v_sale number default 10000;
begin
   insert into xujb_temp1 values('7','卢路',v_sale);
  if
  v_sale>5000 then
  raise_application_error(-20001,'超过上限金额无法录入');
  elsif v_sale<1000 then
  raise_application_error(-20002,'低于金额下限无法录入');
  end if;
  commit;
  exception
      when others then
      dbms_output.put_line('其他异常'||sqlcode||','||sqlerrm);
end;


 
posted @   翻滚的小井蛙  阅读(36)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示