溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Oracle PL/SQL中異常高級(jí)特性示例解析

發(fā)布時(shí)間:2020-10-13 16:03:33 來(lái)源:腳本之家 閱讀:138 作者:C羅的大長(zhǎng)腿 欄目:數(shù)據(jù)庫(kù)

PL/SQL(Procedural Language/SQL,過(guò)程語(yǔ)言/SQL)是結(jié)合了Oracel過(guò)程語(yǔ)言和結(jié)構(gòu)化查詢語(yǔ)言(SQL)的一種擴(kuò)展語(yǔ)言。

優(yōu)點(diǎn):

(1)PL/SQL具有編程語(yǔ)言的特點(diǎn),它能把一組SQL語(yǔ)句放到一個(gè)模塊中,使其更具模塊化種序的特點(diǎn)。

(2)PL/SQL可以采用過(guò)程性語(yǔ)言控制程序的結(jié)構(gòu)。

(3)PL/SQL有自動(dòng)處理的異常處理機(jī)制。

(4)PL/SQL程序塊具有更好的可移植性,可移植到另一個(gè)Oracle數(shù)據(jù)庫(kù)中。

(5)PL/SQL程序減少了網(wǎng)絡(luò)的交互,有助于提高程序性能。

在OraclePL/SQL語(yǔ)句塊中exception的異常處理部分是非常重要的組成部分,它決定了在PL/SQL語(yǔ)句塊內(nèi)部可執(zhí)行部分在發(fā)生異常錯(cuò)誤時(shí),程序是友好地提示:程序遇到某些錯(cuò)誤而無(wú)法執(zhí)行,還是拋出一堆難以理解的Oracle內(nèi)部錯(cuò)誤碼。

  本文只介紹3種PL/SQL異常的三種高級(jí)形態(tài),用于解決Oracle內(nèi)置異常過(guò)少,很多時(shí)候不能夠滿足實(shí)際的使用需求。

1,RAISE_APPLICATION_ERROR

 - 是Oracle提供的一種特殊的內(nèi)置過(guò)程,允許程序員為特定的程序創(chuàng)建有意義的錯(cuò)誤消息,適用于用戶自定義定義異常。
 - 語(yǔ)法結(jié)構(gòu)
  RAISE_APPLICATION_ERROR (error_number,error_message);或者
  RAISE_APPLICATION_ERROR (error_number,error_message,keep_errors)
  - error_number 是與特定錯(cuò)誤消息關(guān)聯(lián)的錯(cuò)誤編號(hào),Oracle預(yù)留了-20999 -- -20000專門(mén)提供給程序員自定義錯(cuò)誤代碼。
  - error_message 是錯(cuò)誤消息文本,最多包含2048個(gè)字符。
  - keep_errors 是可選的Boolean參數(shù),默認(rèn)為FALSE,如果為T(mén)RUE,新拋出的錯(cuò)誤會(huì)被添加到已拋出的錯(cuò)誤列表中,這個(gè)錯(cuò)誤列表稱為錯(cuò)誤棧,如果為FALSE,新錯(cuò)誤會(huì)替換已拋出的錯(cuò)誤棧。
 - 適用于未命名的用戶定義異常,負(fù)責(zé)把錯(cuò)誤編號(hào)和錯(cuò)誤消息關(guān)聯(lián),用戶定義了異常,卻沒(méi)有定義該錯(cuò)誤的名稱
 - 使用RAISE_APPLICATION_ERROR過(guò)程,程序員能夠遵循與Oracle一致的方式返回錯(cuò)誤消息。

 - 示例代碼

declare
 v_id number := &p_id;
 v_name varchar2(20);
 v_sal number;
begin
 if v_id > 0 then
  select ename,sal into v_name,v_sal from emp where empno = v_id;
  dbms_output.put_line(chr(10)||v_name||' '||v_sal);
 else
  raise_application_error (-20001,'Employee id can not be negative.');
 end if;
exception
 when NO_DATA_FOUND then
  dbms_output.put_line(chr(10)||'There is no such employee id is '||v_id); 
end;
/
Enter value for p_id: 40
old 2: v_id number := &p_id;
new 2: v_id number := 40;

There is no such employee id is 40

PL/SQL procedure successfully completed.
/
Enter value for p_id: -90
old 2: v_id number := &p_id;
new 2: v_id number := -90;
declare
*
ERROR at line 1:
ORA-20001: Employee id can not be negative.
ORA-06512: at line 11

 - 示例解析:該P(yáng)L/SQL代碼會(huì)根據(jù)用戶輸入的員工Id,查詢員工的姓名和工資。當(dāng)我們輸入存在的員工編號(hào)時(shí),程序能夠正常返回結(jié)果;如果輸入不存在ID,則select into語(yǔ)句會(huì)拋出沒(méi)有返回行,進(jìn)而使程序進(jìn)入異常處理部分(本部分為舉例),程序同樣執(zhí)行成功;當(dāng)輸入一個(gè)負(fù)數(shù)時(shí),if條件語(yǔ)句就會(huì)進(jìn)入到raise_application_error部分,由于可執(zhí)行部分運(yùn)行發(fā)生錯(cuò)誤,執(zhí)行焦點(diǎn)會(huì)立即轉(zhuǎn)移到異常處理部分,而異常處理部分沒(méi)有關(guān)于該異常的處理,所以程序報(bào)錯(cuò),并返回到用戶界面。

 - 是喲個(gè)raise_application_error,程序員可以使程序?qū)崿F(xiàn)像Oracle系統(tǒng)產(chǎn)生的錯(cuò)誤消息。

 - 事實(shí)上,單純使用raise_application_error,因?yàn)闆](méi)有異常的名稱,如果要對(duì)其進(jìn)行異常處理,只能夠使用others(下文有專門(mén)的介紹)。

2,EXCEPTION_INIT

 - 使用EXCEPTION_INIT編譯指令,可以將用戶自定義的Oracle錯(cuò)誤編號(hào)和用戶自定義的錯(cuò)誤名稱關(guān)聯(lián)起來(lái),相當(dāng)于用戶自定義錯(cuò)誤和RAISE_APPLICATION_ERROR的結(jié)合體。

 - EXCEPTION_INIT 出現(xiàn)在語(yǔ)句塊的聲明部分: 

exception_name exception;
  pragma exception_init(exception_name,error_code)

 - 考慮如下代碼:

declare
 v_no number := &p_no;
begin
 delete from dept where deptno = v_no;
 dbms_output.put_line(chr(10)||'The department id is '||v_no||' has been deleted');
end;
/
Enter value for p_no: 20
old 2: v_no number := &p_no;
new 2: v_no number := 20;
declare
*
ERROR at line 1:
ORA-02292: integrity constraint (SCOTT.FK_DEPTNO) violated - child record found
ORA-06512: at line 4

 - 由于違反外鍵約束,刪除部門(mén)失敗了。但是拋出的錯(cuò)誤不是很好理解

 - 我們可以使用EXCEPTION_INIT來(lái)對(duì)這個(gè)錯(cuò)誤進(jìn)行處理,首先我們得知道違反外鍵約束的這個(gè)Oracle錯(cuò)誤代碼“ORA-02292”

 - 使用EXCEPTION_INIT

declare
 v_no number := &p_no;
 e_dept_exist exception;
 pragma exception_init(e_dept_exist,-02292);
begin
 delete from dept where deptno = v_no;
 dbms_output.put_line(chr(10)||'The department id is '||v_no||' has been deleted');
exception
 when e_dept_exist then
  dbms_output.put_line(chr(10)||'There are some employees in this deptartment, if you want delete this deptartment ,please delete these employees in the department first.');
end;
/ 
Enter value for p_no: 20
old 2: v_no number := &p_no;
new 2: v_no number := 20;
There are some employees in this deptartment, if you want delete this deptartment ,please delete these employees in the department first.
PL/SQL procedure successfully completed.

 - 這下拋出的錯(cuò)誤就容易理解多了。首先我們定義了一個(gè)名為e_dept_exist的異常,然后將這個(gè)異常與Oracle錯(cuò)誤代碼 -02292 進(jìn)行關(guān)聯(lián)。當(dāng)程序執(zhí)行報(bào)錯(cuò)時(shí)進(jìn)入異常處理部分,在這里我們重新給這個(gè)錯(cuò)誤定義了錯(cuò)誤消息。

3,SQLCODE 和 SQLERRM

 - 在異常處理中,當(dāng)異常的名稱未知時(shí)(比如上面1中RAISE_APPLICATION_ERROR),都可以使用others來(lái)進(jìn)行異常的捕獲處理;

 - 由于others所捕獲的異常是未知的(也可以是已知的,但是在程序中沒(méi)有將其枚舉出來(lái)),因此需要使用Oracle提供的兩個(gè)內(nèi)置函數(shù)SQLCODE、SQLERRM來(lái)針對(duì)others的異常進(jìn)行處理:

 - SQLCODE 會(huì)返回Oracle的錯(cuò)誤編號(hào)
 - SQLERRM,返回錯(cuò)誤的消息

 - 示例1,處理Oracle系統(tǒng)返回的錯(cuò)誤:

declare
 v_no number := &p_no;
 error_code number;
 error_msg varchar2(500);
begin
 delete from dept where deptno = v_no;
 dbms_output.put_line(chr(10)||'The department id is '||v_no||' has been deleted');
exception
 when others then
  error_code := sqlcode;
  error_msg := sqlerrm;
  dbms_output.put_line(chr(10)||'Error code is: '||error_code);
  dbms_output.put_line(chr(10)||'Error message is: '||error_msg);
end;
Enter value for p_no: 10
old 2: v_no number := &p_no;
new 2: v_no number := 10;
Error code is: -2292
Error message is: ORA-02292: integrity constraint (SCOTT.FK_DEPTNO) violated - child record found
PL/SQL procedure successfully completed.

 - 請(qǐng)注意exception異常處理部分,在該部分里面我們用到了聲明部分定義的兩個(gè)變量,error_code用來(lái)存儲(chǔ)SQLCODE,error_msg用來(lái)存儲(chǔ)SQLERRM。然后將兩個(gè)變量值打印出來(lái)。

 - 示例2,處理用戶自定義的異常:

declare
 v_id number := &p_id;
 v_name varchar2(20);
 v_sal number;
begin
 if v_id > 0 then
  select ename,sal into v_name,v_sal from emp where empno = v_id;
  dbms_output.put_line(chr(10)||v_name||' '||v_sal);
 else
  raise_application_error (-20001,'Employee id can not be negative.');
 end if;
exception
 when NO_DATA_FOUND then
  dbms_output.put_line(chr(10)||'There is no such employee id is '||v_id); 
 when others then
  declare
   error_code number;
   error_msg varchar2(500);
  begin
   error_code := sqlcode;
   error_msg := sqlerrm;
   dbms_output.put_line(chr(10)||'Error code is: '||error_code);
   dbms_output.put_line(chr(10)||'Error message is: '||error_msg);
  end;
end;
/
Enter value for p_id: -90
old 2: v_id number := &p_id;
new 2: v_id number := -90;
Error code is: -20001
Error message is: ORA-20001: Employee id can not be negative.
PL/SQL procedure successfully completed.

 - 在本代碼中使用了raise_application_error,由于單純的使用raise_application_error,只能使用others進(jìn)行捕獲。在異常處理部分,我們使用了一個(gè)PL/SQL語(yǔ)句塊來(lái)處理這個(gè)錯(cuò)誤,聲明兩個(gè)變量,并將SQLCODE和SQLERRM以字面值賦值的方法給這兩個(gè)變量。

總結(jié)

以上所述是小編給大家介紹的Oracle PL/SQL中異常高級(jí)特性示例解析,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)億速云網(wǎng)站的支持!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI