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)