码迷,mamicode.com
首页 > 数据库 > 详细

Oracle SQL 异常处理

时间:2019-01-22 23:06:46      阅读:455      评论:0      收藏:0      [点我收藏+]

标签:line   多行   app   var   保留   store   varchar   output   字符   

今天学了异常处理

预定义异常用户自定义异常 还有 raise_application_error()函数
raise_application_error() 只能把异常抛出而不能处理异常。

预定义异常包括
– NO_DATA_FOUND --没有找到数据
– TOO_MANY_ROWS --找到多行数据
– INVALID_CURSOR --失效的游标
– ZERO_DIVIDE --除数为零
– DUP_VAL_ON_INDEX –唯一索引中插入了重复值

预定义异常的示例:

declare
    v_id emp.empno%type;           --声明变量
begin
    select empno into v_id from emp where deptno =40;
exception                          --异常处理
    when no_data_found then        --no_data_found 是使用 select 某字段,然后 into 的时候,该字段没有出。
        rollback;
        dbms_output.put_line(没有40号部门记录);
    when too_many_rows then        --too_many_rows 是使用 select 某字段,然后 into 的时候,该字段有多个值。
        rollback;
        dbms_output.put_line(返回多条记录);
    when others then               --其它的异常出现
        rollback;
        dbms_output.put_line(出现其他错误.);
end;

 

用户自定义异常就是用户定义一个异常情况,遇到这种情况再对这种情况进行处理
因为用户定义的异常不一定是oracle返回的系统错误,系统不会自动触发,需要在声明部分定义。用户定义的异常处理部分基本上和预定义异常相同。

declare
    salary_level           varchar2(1);
    invalid_salary_level   exception; --声明异常
begin
    salary_level := D;
    if salary_level not in (A,B,C) then
      raise invalid_salary_level;     --触发异常
    end if;
exception                             --异常处理
    when invalid_salary_level then
      dbms_output.put_line(invalid salary level);
end;

 

raise_application_error() 函数只是将异常抛出,不进行异常处理,并且终止程序。而用户自定义异常以及预定义异常不回终止程序,但会终止该 PL/SQL 代码块,所以一个存储过程中可以有多个 PL/SQL 代码块。

关于异常的语法及定义:

什么是异常:

PL/SQL用异常和异常处理器来实现错误处理
Oracle中出现错误的情形通常分为编译时错误(compile-time error)和运行时错误(run-time error)。
异常在PL/SQL执行过程中很可能出现
对异常如果不进行处理,异常可能会中断程序的运行

捕获异常的规则:

在异常部分WHEN 子句没有数量限制
当异常抛出后,控制无条件转到异常处理部分
EXCEPTION 关键词开始异常处理部分 WHEN OTHERS 为最后的一条子句
在异常块中,只有一个句柄会处理异常

关于异常捕获的函数:

SQLCODE 返回错误代码
SQLERRM 返回与错误代码关联的消息

保存任何非预期的异常的错误编码和错误消息

declare
  v_error_code      NUMBER;
  v_error_message   VARCHAR2(255);
BEGIN
EXCEPTION
     WHEN OTHERS THEN
         ROLLBACK;
         v_error_code := SQLCODE;
         v_error_message := SQLERRM;
      INSERT INTO err_logs VALUES (v_error_code,  v_error_message);
END;

异常的传播

PL/SQL中错误处理的步骤:
步骤1:如果当前块中有该异常的处理器,则执行该异常处理语句块,然后控制权传递到外层语句块 步骤2:如果没有当前异常的处理器,把该异常传播给外层块。然后在外层执行步骤1。如果此语句在最外层语句块,则该异常将被传播给调用环境

没有处理的异常将沿检测异常调用程序传播到外面,当异常被处理并解决或到达程序最外层传播停止。异常是自里向外逐级传递的。

小题:

1.根据员工号,获得员工到目前为止参加工作年限(保留到整数),员工号不存在时提示“此员工号不存在”。

create or replace function get_workyear
    (v_id in emp.empno%type)
    return varchar2
IS
    v_workyear integer;
BEGIN
    select to_char(sysdate,yyyy)-to_char(hiredate,yyyy) --两个数字字符串相减的值存到整数型变量中
    into v_workyear 
    from emp
    where emp.empno = v_id;
    return v_workyear;
EXCEPTION
    when no_data_found then
      dbms_output.put_line(此员工号不存在);
      return -1;
END get_workyear;

2.

①建表myemp,和额,emp一样
②建存储过程,存储过程要的参数,和表里的字段一一对应,比如,表里有empno,存储过程就要有一个参数对应这字段i_empno,类型肯定和empno一样,如果你知道类型是number(4),就直接写成(i_empno in number(4),...)以此类推.
③功能实现,根据empno判断,如果myemp表里已经有这个empno,你就根据你传入的信息把empno的信息更新了,如果没有,就把你这些传入的字段,插入到表里,
eg:我只用两个字段来说明,empno,sal,
入参1:123,1000,经过判断,myemp表里没有123这个empno,那么执行完存储过程,这个信息要插入到表里,
入参2:7369,2000,经判断,表里已经有这个编号,但是sal为800,那么执行完存储过程,7369的sal要是2000
create or replace procedure store_info
    (v_empno      in        myemp.empno%type,
     v_ename      in        myemp.ename%type,
     v_job        in        myemp.job%type,
     v_mgr        in        myemp.mgr%type,
     v_hiredate   in        myemp.hiredate%type,
     v_sal        in        myemp.sal%type,
     v_comm       in        myemp.comm%type,
     v_deptno     in        myemp.deptno%type
    )
IS
    v_id myemp.empno%type:=0;
BEGIN
    select count(*) into v_id 
    from myemp 
    where myemp.empno = v_empno;
    if (v_id=0) then 
        insert into myemp(empno, ename, job, mgr, hiredate, sal, comm, deptno)
        values (v_empno,v_ename,v_job,v_mgr,v_hiredate,v_sal,v_comm,v_deptno); 
    else 
        update myemp
        set myemp.ename=nvl(v_ename,myemp.ename) , myemp.job=nvl(v_job,myemp.job),
            myemp.mgr=nvl(v_mgr,myemp.mgr) , myemp.hiredate=nvl(v_hiredate,myemp.hiredate),
            myemp.sal=nvl(v_sal,myemp.sal) , myemp.comm=nvl(v_comm,myemp.comm),
            myemp.deptno=nvl(v_deptno,myemp.deptno)
    where myemp.empno = v_empno ;
    end if;
END store_info;

begin 
  store_info(7369,null,null,null,null,2000,null,null);
end;

 

附一张图:

技术分享图片

 

Oracle SQL 异常处理

标签:line   多行   app   var   保留   store   varchar   output   字符   

原文地址:https://www.cnblogs.com/jiaxinwei/p/10306309.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!