1、PL/SQL编程基础 异常处理,1 什么是异常处理,*异常处理,仅用来处理PL/SQL运行时错误。,什么是异常? 在PL/SQL中的一个标识。 在程序运行期间被触发的错误。 异常是怎样被触发的? 产生一个Oracle错误。 用户显示触发。 怎样处理异常? 用异常处理句柄捕获异常。 传播异常到调用环境。,2 异常处理,异常被触发,异常被捕获,传播异常,异常被触发,异常没有被捕获,捕获异常,2.1 异常处理语法,EXCEPTIONWHEN exception1 OR exception2 . . . THENstatement1;statement2;. . .WHEN exception3 OR
2、 exception4 . . . THENstatement1;statement2;. . .WHEN OTHERS THENstatement1;statement2;. . .,2.2 捕获异常规则,WHEN OTHERS用于捕获所有未指定错误。必须是最后一个错误处理语句。 EXCEPTION关键字,标识异常处理的开始区域。 允许有多个异常处理子句。 在离开异常处理程序块之前,只能有一个错误处理子句被执行。,3 异常的类型,隐式触发,显式触发,系统预定义异常 系统非预定义异常用户自定义异常,3.1 系统预定义异常,CASE_NOT_FOUND (ORA-06592) NO_DATA_F
3、OUND (ORA-1403) TOO_MANY_ROWS (ORA-1422) DUP_VAL_ON_INDEX (ORA-0001)ZERO_DIVIDE (ORA-1476) INVALID_CURSOR (ORA-1001) VALUE_ERROR (ORA-6502),3.1 系统预定义异常,BEGIN SELECT . COMMIT; EXCEPTIONWHEN NO_DATA_FOUND THENstatement1; statement2; WHEN TOO_MANY_ROWS THENstatement1;WHEN OTHERS THENstatement1; stateme
4、nt2; statement3; END;,语法,3.1 系统预定义异常,DECLAREv_empRecord emp%ROWTYPE; v_empNo emp.empno%TYPE; BEGIN SELECT * INTO v_empRecord FROM emp;-SELECT * INTO v_empRecord FROM emp WHERE empno = 12345789 ;-SELECT ename INTO v_empNo FROM emp WHERE empno = 7369;EXCEPTIONWHEN TOO_MANY_ROWS THENdbms_output.put_lin
5、e(TOO_MANY_ROWS EXCEPTION); WHEN NO_DATA_FOUND THENdbms_output.put_line(NO_DATA_FOUND EXCEPTION); WHEN OTHERS THENdbms_output.put_line(OTHERS EXCEPTION); END;,3.2 非预定义异常,Name the exception,Code the PRAGMA EXCEPTION_INIT,Declarative Section,Handle the raised exception,Exception-Handling Section,将一个经过
6、命名的异常和一个特别的Oracle错误编号相关联。,DECLAREe_products_invalid EXCEPTION;PRAGMA EXCEPTION_INIT (e_products_invalid, -2292);v_message VARCHAR2(50); BEGIN . . . EXCEPTIONWHEN e_products_invalid THEN:g_message := Product codespecified is not valid.; . . . END;,3.2 非预定义异常,1,2,3,捕获Oracle服务器错误 将数字-2292与e_products_in
7、valid相关联。(-2292表示违反了完整性约束),3.2 非预定义异常,CREATE OR REPLACE PROCEDURE insert_emp (no IN emp.empno%TYPE, name IN emp.ename%TYPE DEFAULT NULL, job IN emp.job%TYPE DEFAULT SALESMAN, mgr IN emp.mgr%TYPE DEFAULT 7369, hiredate emp.hiredate%TYPE DEFAULT SYSDATE, salary emp.sal%TYPE DEFAULT 800, comm m%TYPE DE
8、FAULT NULL, deptno emp.deptno%TYPE DEFAULT 10 )IS e_integrity EXCEPTION; PRAGMA EXCEPTION_INIT (e_integrity,-2291); BEGININSERT INTO emp VALUES(no,name,job,mgr,hiredate,salary,comm,deptno); EXCEPTIONWHEN DUP_VAL_ON_INDEX THENdbms_output.put_line(该员工已经存在!);WHEN e_integrity THENdbms_output.put_line(部门
9、编号填写错误!); END;,例子: 为emp表创建一个能完成插入功能的存储过程insert_emp。,3.3 用户自定义异常,Declarative Section,Executable Section,Exception-Handling Section,3.3 用户自定义异常,DECLAREe_amount_remaining EXCEPTION; . . . BEGIN . . .RAISE e_amount_remaining; . . . EXCEPTIONWHEN e_amount_remaining THEN:g_message := There is still an amo
10、untin stock.; . . . END;,例子:,1,2,3,3.3 用户自定义异常,DECLARE ex_null EXCEPTION; -系统非预定义异常的定义和关联PRAGMA EXCEPTION_INIT(ex_null,-01400); ex_insert EXCEPTION; -用户自定义异常的定义 eno scott.emp.empno%TYPE:=,例子: 向emp表中插入一条新记录,在执行的过程中捕获系统预定义异常、系统非预定义异常、用户自定义异常,并分别作相应的处理。,4 捕获异常中的函数,SQLCODE 返回错误代码。SQLERRM 返回与错误代码相关联的消息。,
11、DECLAREv_error_code NUMBER;v_error_message VARCHAR2(255); BEGIN . EXCEPTION .WHEN OTHERS THENROLLBACK;v_error_code := SQLCODE ;v_error_message := SQLERRM ;INSERT INTO errors VALUES(v_error_code,v_error_message); END;,5 传播异常,BEGINSELECT .UPDATE .IF SQL%NOTFOUND THENRAISE e_no_rows;END IF; EXCEPTIONWH
12、EN e_integrity THEN .WHEN e_no_rows THEN . END;,DECLARE. . .e_no_rows exception;e_integrity exception;PRAGMA EXCEPTION_INIT (e_integrity, -2292); BEGINFOR c_record IN emp_cursor LOOP,END LOOP; EXCEPTIONWHEN NO_DATA_FOUND THEN . . .WHEN TOO_MANY_ROWS THEN . . . END;,嵌入块能够处理异常或传递异常到它的上层块,BEGINSELECT .
13、UPDATE .IF SQL%NOTFOUND THENRAISE e_no_rows;END IF; EXCEPTIONWHEN e_integrity THEN .WHEN e_no_rows THEN . END;,5 传播异常,raise_application_error (error_number,message, TRUE | FALSE);,.EXCEPTIONWHEN NO_DATA_FOUND THENRAISE_APPLICATION_ERROR (-20201,Manager is not a valid employee.);END;,语法从存储过程中触发用户自定义异常。,Thank You! The End,