1. 程式人生 > >Oracle SQL 異常處理

Oracle SQL 異常處理

傳播 保留 並且 插入 技術分享 情況 lin 多行 ger

今天學了異常處理

預定義異常用戶自定義異常 還有 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 異常處理