plsql的錯誤信息與異常處理

7 錯誤消息與異常處理

7.1 異常的介紹

(1) 處理異常分為三個步驟:
  A 聲明異常
  B 引發(fā)異常
  C 處理異常

(2) 異常的特征
  A 錯誤類型: ORA-xxxxx  運行時錯誤
               PLS-xxxxx  編譯錯誤
  B 錯誤代碼:xxxxx
  C 錯誤的文本描述

案例1:編譯錯誤的案例PLS

SQL> create or replace procedure p1 is
  2  begin
  3  null;
  4  end;
  5  /

Procedure created.

SQL> create or replace procedure p1 is
  2  begin
  3  null           --特意不寫分號
  4  end;
  5  /

Warning: Procedure created with compilation errors.         --出現(xiàn)警告

SQL> show error     --查看錯誤消息
Errors for PROCEDURE P1:

LINE/COL ERROR
-------- -----------------------------------------------------------------
4/1     PLS-00103: Encountered the symbol "END" when expecting one of the
     following:
     ;
     The symbol ";" was substituted for "END" to continue.

案例2:運行時錯誤 -- 在編譯的時候沒有錯誤,但是在執(zhí)行的時候發(fā)生錯誤。

SQL> create or replace procedure p2 is
  2   v_descr varchar2(20);
  3  begin
  4   select hrc_descr
  5     into v_descr
  6    from hrc_tab
  7   where hrc_code=8;
  8  dbms_output.put_line(to_char(v_descr));
  9  end;
 10  /

Procedure created.

SQL> exec p2;       --運行一個存儲過程
BEGIN p2; END;

*
ERROR at line 1:
ORA-01403: no data found
ORA-06512: at "PLSQL.P2", line 4
ORA-06512: at line 1

總結:
 A PLSQL錯誤 -- 編譯錯誤,在執(zhí)行之前就已經報錯,需要檢查程序,修改程序,debug
 B ORA錯誤   -- 運行時錯誤,出現(xiàn)這種錯誤的時候需要手工處理,可以采用第三方軟件的單步調試方式處理

(2) 異常處理中的聲明,分為三個部分

 A exception聲明,在聲明自己定義異常的時候需要用到這個方法。
 B raise語句:顯示地引發(fā)異常
 C pragma excetption_init 這個指令可以將oracle錯誤和自己定義異常關聯(lián)起來

 函數(shù)(需要定義變量來接收)
     
    sqlcode -- 返回錯誤的代碼號,如果沒有錯誤就返回0,可以根據sqlcode返回的值查詢官方文檔,獲得更詳細的錯誤描述
    sqlerrm -- 返回錯誤的文本描述,如果沒有錯誤返回normal或者successful completion,也就是官方文檔定義的錯誤

(3) 異常處理的常見案例
declare
  v_descr varchar2(20);
begin
  select hrc_descr
    into v_descr
    from hrc_tab
   where hrc_code=8;
  dbms_output.put_line(v_descr);
exception when no_data_found then       --異常的名稱
  dbms_output.put_line('not exists');
end;

no_data_found  --oracle預定義好的異常的名稱,oracle官方文檔上有每個異常名稱描述和引發(fā)的場景介紹
《PL/SQL User's Guide and Reference》pdf版本中第264頁

sqlcode與sqlerrm兩個函數(shù)的使用

declare
  v_descr varchar2(20);
  v_sqlcode number;
  v_sqlerrm varchar2(200);
begin
  select hrc_descr
    into v_descr
    from hrc_tab
   where hrc_code=8;
  dbms_output.put_line(v_descr);
exception when no_data_found then
  v_sqlcode:=sqlcode;
  v_sqlerrm:=sqlerrm;
  dbms_output.put_line('not exists');
  dbms_output.put_line('ERR: an error with info :'||to_char(v_sqlcode));
  dbms_output.put_line(v_sqlerrm);
end;

輸出:
not exists
ERR: an error with info :100        --100是錯誤的代碼號,其他的錯誤sqlcode都是ora-后面的號碼,這個異常特殊
ORA-01403: no data found            --錯誤的描述

對程序的異常進行處理,讓程序不會在發(fā)生異常

declare
  v_descr varchar2(20);
  v_sqlcode number;
  v_sqlerrm varchar2(200);
begin
  select hrc_descr
    into v_descr
asdfasdg    from hrc_tab
   where hrc_code=8;
  dbms_output.put_line(v_descr);
exception when no_data_found then
  v_sqlcode:=sqlcode;
  v_sqlerrm:=sqlerrm;
  dbms_output.put_line('not exists');
  dbms_output.put_line('ERR: an error with info :'||to_char(v_sqlcode));
  dbms_output.put_line(v_sqlerrm);
  insert into hrc_tab values(8,'asdfasdg');
  commit;
end;

第一次運行

輸出:
not exists
ERR: an error with info :100       
ORA-01403: no data found

再一次運行
輸出:
asdfasdg

(4)PLSQL異常的功能性分類

  A 預定義的異常  oracle自己預先定義好的
  B 用戶自定義的異常

 用戶自定義的異常

declare
  site_s_undefined_for_org exception;
  v_cnt number;
begin
  select count(*) into v_cnt from org_site_tab where org_id=1007;  --本身查詢是沒問題的
  if v_cnt=0 then      --只有在v_cnt值為0的時候引發(fā)異常
    raise site_s_undefined_for_org;
  end if;
exception when site_s_undefined_for_org then
  dbms_output.put_line('empty table!');
  when others then
  dbms_output.put_line('ERR: an error with info :'||to_char(sqlcode));
  dbms_output.put_line(sqlerrm);
end;

--自己定義異常,自己拋出異常,自己處理異常

系統(tǒng)預定義的異常

DUP_VAL_ON_INDEX   --唯一性約束上有列值的重復沖突

declare
  site_s_undefined_for_org exception;
  v_cnt number;
begin
  select count(*) into v_cnt from org_site_tab where org_id=1007;  --本身查詢是沒問題的
  insert into hrc_tab values(8,'asfdadsagsa');--這里出現(xiàn)異常,程序就進入異常處理部分,后面不再執(zhí)行
  commit;
  if v_cnt=0 then      --只有在v_cnt值為0的時候引發(fā)異常
    raise site_s_undefined_for_org;
  end if;
exception when site_s_undefined_for_org then
  dbms_output.put_line('empty table!');
  when DUP_VAL_ON_INDEX then
  dbms_output.put_line('value repeat!');
  when others then
  dbms_output.put_line('ERR: an error with info :'||to_char(sqlcode));
  dbms_output.put_line(sqlerrm);
end;

輸出:value repeat!

(3) pragma exception_init 指令
 這個指令就是把oracle的錯誤還有用戶自定義異常關聯(lián)起來

[oracle@test ~]$ oerr ora 02290     --知道錯誤號,可以使用該命令查看詳細錯誤
02290, 00000, "check constraint (%s.%s) violated"
// *Cause: The values being inserted do not satisfy the named check
//    constraint.
// *Action: do not insert values that violate the constraint.


select * from user_constraints where table_name='ORG_LEVEL';

SQL> conn plsql/plsql
Connected.
SQL> insert into org_level values(1001,'P');
insert into org_level values(1001,'P')
*
ERROR at line 1:
ORA-02290: check constraint (PLSQL.ORG_LEVEL_CK) violated


declare
  invalid_org_level exception;
  pragma exception_init(invalid_org_level,-2290);  --關聯(lián)以后,就不需要raise引發(fā)異常
begin
create table exception_monitor(
excep_tab_name varchar2(30),
excep_key varchar2(50),
excep_program varchar2(30),
excep_name varchar2(30),
excep_code number,
excep_txt varchar2(200),
excep_date date
);
  insert into org_level values(1001,'P');
  commit;
exception when invalid_org_level then
  dbms_output.put_line('ERR:an error with info :'||to_char(sqlcode));
  dbms_output.put_line(sqlerrm);
  when others then
  dbms_output.put_line('ERR:an error with info :'||to_char(sqlcode));
  dbms_output.put_line(sqlerrm);
end;

可以讓程序自己拋出

begin
  insert into org_level values(1001,'P');
  commit;
exception
  when others then
  dbms_output.put_line('ERR:an error with info :'||to_char(sqlcode));
  dbms_output.put_line(sqlerrm);
end;

##########################################################################################

成都創(chuàng)新互聯(lián)長期為千余家客戶提供的網站建設服務,團隊從業(yè)經驗10年,關注不同地域、不同群體,并針對不同對象提供差異化的產品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網生態(tài)環(huán)境。為阿巴嘎企業(yè)提供專業(yè)的網站制作、成都網站設計,阿巴嘎網站改版等技術服務。擁有10多年豐富建站經驗和眾多成功案例,為您定制開發(fā)。


7.2 異常監(jiān)控表

(1) 創(chuàng)建一個異常監(jiān)控表:exception_monitor

字段
   發(fā)生異常的表的名字:    excep_tab_name
   發(fā)生異常的行的主鍵:    excep_key
   發(fā)生異常的程序的名稱:  excep_program,如果是匿名塊就置為null
   異常的名稱:            excep_name 如果沒有定義就寫'others'
   異常的sqlcode:          excep_code
   異常的文本描述:        excep_txt
   發(fā)生異常的時間:        excep_date

以后編寫程序的時候都要編寫異常處理部分,獲取到上面這些信息,插入這個表

創(chuàng)建異常監(jiān)控表:
create table exception_monitor(
excep_tab_name varchar2(30),
excep_key varchar2(50),
excep_program varchar2(30),
excep_name varchar2(30),
excep_code number,
excep_txt varchar2(200),
excep_date date
);

改寫上面的例子:
declare
  invalid_org_level exception;
  pragma exception_init(invalid_org_level,-2290);
  v_sqlcode number;
  v_sqlerrm varchar2(200);
begin
  insert into org_level values(1001,'P');
  commit;
exception when invalid_org_level then
  v_sqlcode:=sqlcode;
  v_sqlerrm:=sqlerrm;
  insert into exception_monitor values('ORG_LEVEL','1001',null,upper('invalid_org_level'),v_sqlcode,v_sqlerrm,sysdate);
  commit;
  when others then
  v_sqlcode:=sqlcode;
  v_sqlerrm:=sqlerrm;
  insert into exception_monitor values('ORG_LEVEL','1001',null,upper('others'),v_sqlcode,v_sqlerrm,sysdate);
  commit;
end;

練習7:將練習6那個程序修改它的異常處理部分,將錯誤捕獲到監(jiān)控表

錯誤號的20000~21299是錯誤號的空缺范圍,這個范圍用來自定義錯誤,用內置的函數(shù)來引發(fā)這個錯誤。

declare
  site_s_undefined_fo_org exception;
  pragma exception_init(site_s_undefined_fo_org,-20001);
  v_cnt number;
begin
  select count(1) into v_cnt from org_site_tab where org_id=1007;
  if v_cnt=0 then
    raise_application_error(-20001,'this table rows is empty!');
  end if;
exception when site_s_undefined_fo_org then
  dbms_output.put_line(sqlerrm);
  when others then
  dbms_output.put_line('ERR : an error with info :'||to_char(sqlcode));
  dbms_output.put_line(sqlerrm);
end;

不關聯(lián)異常的名稱也可以:

declare
  v_cnt number;
begin
  select count(1) into v_cnt from org_site_tab where org_id=1007;
  if v_cnt=0 then
    raise_application_error(-20001,'this table rows is empty!');
  end if;
exception
  when others then
  dbms_output.put_line('ERR : an error with info :'||to_char(sqlcode));
  dbms_output.put_line(sqlerrm);
end;

##########################################################################################

7.3 在聲明部分引發(fā)的異常的處理

注意:異常需要在begin 和 exception 之間才能捕獲到的

declare
  v_cnt number(2):=100;
begin
  null;
exception when others then
  dbms_output.put_line('ERR CODE : '||to_char(sqlcode));
  dbms_output.put_line(sqlerrm);
end;

改寫:

begin
  declare
    v_cnt number(2):=100;
  begin
    null;
  exception when others then
    dbms_output.put_line('ERR CODE : '||to_char(sqlcode));
    dbms_output.put_line(sqlerrm);
  end;
exception when others then
  dbms_output.put_line('ERR CODE : '||to_char(sqlcode));
  dbms_output.put_line(sqlerrm);
end;

解決方法:將原來的代碼塊嵌套在一個begin和exception之間即可捕獲到

注意:
 A 程序是從begin開始執(zhí)行的,declare部分不是程序執(zhí)行的部分
 B 異常捕獲的區(qū)間是begin到exception之間的代碼

7.5 在異常部分引發(fā)異常的處理

declare
  condition boolean:=true;
  excep1 exception;
  excep2 exception;
begin
  if condition then
    raise excep1;
  end if;
exception when excep1 then
  raise excep2;
end;

改寫:

declare
  condition boolean:=true;
  excep1 exception;
  excep2 exception;
begin
  if condition then
    raise excep1;
  end if;
exception when excep1 then
  begin
    raise excep2;
  exception when excep2 then
    dbms_output.put_line('ERR CODE : '||to_char(sqlcode));
    dbms_output.put_line(sqlerrm);
  end;
end;

或者

declare
  condition boolean:=true;
  excep1 exception;
  excep2 exception;
begin
  begin
    if condition then
      raise excep1;
    end if;
  exception when excep1 then
    raise excep2;
  end;
exception when excep2 then
  dbms_output.put_line('ERR CODE : '||to_char(sqlcode));
  dbms_output.put_line(sqlerrm);
end;

7.6 一個異??梢员欢啻我l(fā)

declare
  condition boolean:=true;
  excep1 exception;
begin
  begin
    if condition then
      raise excep1;
    end if;
  exception when excep1 then
    raise excep1;
  end;
exception when excep1 then
  dbms_output.put_line('ERR CODE : '||to_char(sqlcode));
  dbms_output.put_line(sqlerrm);
end;

新聞名稱:plsql的錯誤信息與異常處理
文章路徑:http://muchs.cn/article0/pppdio.html

成都網站建設公司_創(chuàng)新互聯(lián),為您提供外貿網站建設、網站改版網站維護、品牌網站設計、域名注冊手機網站建設

廣告

聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

搜索引擎優(yōu)化