oracle错误处理明细
oracle异常处理明细Sql代码??exception???????when?first_exception?then?handle?first?exception??????
oracle异常处理明细
Sql代码??
- exception???
- ????when?first_exception?then?<handle?first?exception>??
- ????when?second_exception?then?<handle?second?exception>??
- ????when?others?then?<handle?other?exception>??
在异常处理中,用来获取异常代码和完整错误提示信息的两个子系统函数是sqlcode和sqlerrm。?
对系统内部异常可通过sqlcode返回一个oracle错误编码号。sqlcode返回的编号除了“ora_01403没发现数据”是正值之外,其他的都是负值。?
sqlerrm则返回异常代码相对应的错误信息。对用户定义的异常,sqlcode返回+1而且sqlerrm返回“用户定义异常”。如果没有异常发生,操作正常执行,则sqlcode返回0,sqlerrm返回信息“ora_0000:正常,成功完成”。?
非预定义的Oracle异常?
pragma exception_init(<exception_name>,<handle_code>)?
在PL*SQL中,pragma exception_init告诉编译器将一个Oracle错误编号与异常名建立起来?
Sql代码??

- pragma?exception_init的用法??
- declare???
- ?e_emp_remaining?EXCEPTION;??
- ?pragma?exception_init(e_emp_remaining?,-2292);??
- begin??
- ?delete?from?dept?where?deptno=10;??
- commit;??
- EXCEPTION???
- ????when?(e_emp_remaining?then??
- ????????dbms_output.put_line('cannot?remove?dept'||to_char(10)||'.employee?exist.');??
- end;??
用户自定义异常?
Sql代码??

- declare??
- ?v_eno?emp.empno%type?:=&.empno;??
- ?not_found?exception;??
- begin??
- ?update?emp?set?sal=sal*1.1?where??empno=v_eno;??
- ?if??SQL%?notfound?then??
- ??
- ???raise?not_found//?使用RAISE语句抛出异常??
- ??
- ?end?if;??
- exception??
- ?when?not_found?then??
- ??????dbms_output.put_line('You?can't?update?the?sal,the?number?does?not!exist!');??
- when?others?then??
- ??????dbms_output.put_line('other?other');??
- end??
RAISE_APPLICATION_ERROR?
可能不是很多人知道 RAISE_APPLICATION_ERROR 的用途是什么,虽然从字面上已经猜到这个函数是干什么用的。?
????? 其实 RAISE_APPLICATION_ERROR 是将应用程序专有的错误从服务器端转达到客户端应用程序。?
???
Sql代码??

- RAISE_APPLICATION_ERROR?的声明:??
- ??
- ??PROCEDURE?RAISE_APPLICATION_ERROR?(error_number_in?IN?NUMBER,?error_msg_in?IN?VARCHAR2);??
????? 里面的错误代码和内容,都是自定义的。说明是自定义,当然就不是系统中已经命名存在的错误类别,是属于一种自定义事务错误类型,才调用此函数。?
????? error_number_in 之容许从 -20000 到 -20999 之间,这样就不会与 ORACLE 的任何错误代码发生冲突。?
????? error_msg_in 的长度不能超过 2K,否则截取 2K。?
举个例吧:?
阻止小于18岁的用户增加到数据库 employee 表中?
Sql代码??

- CREATE?OR?REPALCE?TRIGGER?minimun_age_check??
- BEFORE?INSERT?ON?employee??
- FOR?EACH?ROW??
- BEGIN??
- ??????IF?ADD_MONTHS(?:new.birth_date,?18*12)?>?SYSDATE??
- ??????THEN??
- ?????????RAISE_APPLICATION_ERROR(-20001,?'Employees?must?at?least?eighteen?years?of?age.');??
- ??????END?IF;??
- END;??
在客户端,你可以写一个类似下面的程序,来测试一下。?
Sql代码??

- DECLARE??
- ???
- ????no_babies_allowed?EXCEPTION;??
- ???
- ?????/*将名称与用于触发器中的错误号码关联起来*/??
- ?????PRAGMA?EXCEPTION_INIT(no_babies_allowed,?-20001);??
- ???
- BEGIN??
- ???
- ???????INSERT?INTO?employee?....;??
- ???
- EXCEPTION??
- ???????WHEN?no_babies_allowed??
- ???????THEN??
- ??????????????/*??
- ??????????????||?SQLERRM?将传递给内置过程?RAISE_APPLICATION_ERROR?的消息返回??
- ??????????????*/??
- ??????????????DBMS_OUTPUT.PUT_LINE(SQLERRM);??
- END; ?
?
将异常作为控制语句
因为引发异常会将程序的控制逻辑转移到代码块的异常处理部分,所以可以将RAISE语句用作控制语句,就像GOTO语句一样。例如,如果我们有很深的嵌套循环,并需要立即从中退出的时候,这可能会非常有用。