oracle数据库----笔记1---PL/SQL基础4---异常处理
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;