oracle 异常

来源:互联网 发布:淘宝上可信的小样店铺 编辑:程序博客网 时间:2024/06/05 16:49
有三种类型的异常错误:


    1. 内部异常 ( Internally defined )异常


  ORACLE内部异常有25个。对这种异常情况的处理,无需在程序中定义,由ORACLE自动将其引发,内部异常包含异常名和异常代码和异常消息。


    2. 预定义 ( Predefined )异常


   即其他标准的ORACLE错误。对这种异常情况的处理,需要用户在程序中定义,然后由ORACLE自动将其引发,预定义异常只包含异常代码和异常消息,不包含异常名称。


    3. 用户自定义(User-define) 异常


 程序执行过程中,出现编程人员认为的非正常情况。对这种异常情况的处理,需要用户在程序中定义,然后显式地在程序中将其引发。


--内部异常的使用
例1:更新指定员工工资,如工资小于1500,则加100;
登录SCOTT用户
DECLARE
   v_empno emp.empno%TYPE := '&empno';
   v_sal   emp.sal%TYPE:=0;
BEGIN
   SELECT sal INTO v_sal FROM emp WHERE empno = v_empno;
   IF v_sal<=1500 THEN 
        UPDATE emp SET sal = sal + 100 WHERE empno=v_empno; 
        DBMS_OUTPUT.PUT_LINE('编码为'||v_empno||'员工工资已更新!');     
   ELSE
        DBMS_OUTPUT.PUT_LINE('编码为'||v_empno||'员工工资已经超过规定值!');
   END IF;
EXCEPTION
   WHEN NO_DATA_FOUND THEN  
      DBMS_OUTPUT.PUT_LINE('数据库中没有编码为'||v_empno||'的员工');
   WHEN TOO_MANY_ROWS THEN
      DBMS_OUTPUT.PUT_LINE('程序运行错误!请使用游标');
   WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE('错误提示:'||SQLCODE||'---'||SQLERRM);
END; 
/




--预定义异常的使用
例2:删除指定部门的记录信息,以确保该部门没有员工。


INSERT INTO dept VALUES(50, 'FINANCE', 'CHICAGO');
commit;
select * from dept;
DECLARE
   v_deptno dept.deptno%TYPE := '&deptno';
   deptno_remaining EXCEPTION;
   PRAGMA EXCEPTION_INIT(deptno_remaining, -2292);
   /* -2292 是违反一致性约束的错误代码 */
BEGIN
   DELETE FROM dept WHERE deptno = v_deptno;
EXCEPTION
   WHEN deptno_remaining THEN 
      DBMS_OUTPUT.PUT_LINE('违反数据完整性约束!');
   WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);
END;
/




--RAISE的使用
例3:更新指定员工工资,增加100;


DECLARE
   v_empno emp.empno%TYPE :=&empno;
   no_result  EXCEPTION;
BEGIN
   UPDATE emp SET sal = sal+100 WHERE empno = v_empno;
   IF SQL%NOTFOUND THEN
      RAISE no_result;
   END IF;
EXCEPTION
   WHEN no_result THEN 
      DBMS_OUTPUT.PUT_LINE('你的数据更新语句失败了!');
   WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);
END;
/




可能不是很多人知道 RAISE_APPLICATION_ERROR 的用途是什么,虽然从字面上已经猜到这个函数是干什么用的。平时用来测试的异常处理
我们都是通过dbms_output.put_line来输出异常信息,但是在实际的应用中,需要把异常信息返回给调用的客户端。
其实 RAISE_APPLICATION_ERROR 是将应用程序专有的错误从服务器端转达到客户端应用程序(其他机器上的SQLPLUS或者其他前台开发语言)


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。
举个例吧:






declare
l_n number:=&n;
/* is_oushu exception;  --是偶数
 PRAGMA EXCEPTION_INIT(is_oushu, -20000);*/
begin
  if mod(l_n,2)=0 then
    RAISE_APPLICATION_ERROR(-20001, '是偶数');--如果是偶数则抛出异常
  end if;
  exception 
    when others 
      then dbms_output.put_line('wrong:'||sqlerrm);
end;
/


--用EXCEPTION_INIT来实现
declare
l_n number:=&n;
 is_oushu exception;  --是偶数
 PRAGMA EXCEPTION_INIT(is_oushu, -20000);
begin
  if mod(l_n,2)=0 then
    raise is_oushu;
  end if;
  exception 
    when is_oushu 
      then dbms_output.put_line('错误'||sqlerrm);
end;
/




--用RAISE_APPLICATION_ERROR 自定义异常


CREATE TABLE errlog(
  Errcode NUMBER,
  Errtext CHAR(40));


CREATE OR REPLACE FUNCTION get_salary(p_deptno NUMBER)
RETURN NUMBER 
AS
  v_sal NUMBER;
BEGIN
  IF p_deptno IS NULL THEN
    RAISE_APPLICATION_ERROR(-20991, '部门代码为空');
  ELSIF p_deptno<0 THEN
    RAISE_APPLICATION_ERROR(-20992, '无效的部门代码');
  ELSE
    SELECT SUM(emp.sal) INTO v_sal FROM emp 
    WHERE emp.deptno=p_deptno;
    RETURN v_sal;
  END IF;
END;
/


DECLARE 
  V_salary NUMBER(7,2);
  V_sqlcode NUMBER;
  V_sqlerr VARCHAR2(512);
  Null_deptno EXCEPTION;
  Invalid_deptno EXCEPTION;
  PRAGMA EXCEPTION_INIT(null_deptno,-20991);
  PRAGMA EXCEPTION_INIT(invalid_deptno, -20992);
BEGIN
  V_salary :=get_salary(10);
  DBMS_OUTPUT.PUT_LINE('10号部门工资:' || TO_CHAR(V_salary));
  BEGIN
    V_salary :=get_salary(-10);
  EXCEPTION
    WHEN invalid_deptno THEN
      V_sqlcode :=SQLCODE;
      V_sqlerr  :=SQLERRM;
      INSERT INTO errlog(errcode, errtext) 
      VALUES(v_sqlcode, v_sqlerr);
      COMMIT;
  END ;


  V_salary :=get_salary(20);
  DBMS_OUTPUT.PUT_LINE('部门号为20的工资为:'||TO_CHAR(V_salary));


  BEGIN
    V_salary :=get_salary(NULL);
  END ;
  V_salary := get_salary(30);
  DBMS_OUTPUT.PUT_LINE('部门号为30的工资为:'||TO_CHAR(V_salary));


  EXCEPTION
    WHEN null_deptno THEN
      V_sqlcode :=SQLCODE;
      V_sqlerr  :=SQLERRM;
      INSERT INTO errlog(errcode, errtext) VALUES(v_sqlcode, v_sqlerr);
      COMMIT;
    WHEN OTHERS THEN
         DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM);
END ;
/


EXCEPTION_INIT和RAISE_APPLICATION_ERROR的区别


EXCEPTION_INIT的特点
1.用来调用预定义异常和用户自定义异常
2.调用时已经存在异常名称


RAISE_APPLICATION_ERROR的特点
1.不需要预定义而直接抛出异常
2.不用定义异常名称



0 0
原创粉丝点击