PL/SQL 異常處理

2021-08-30 15:59 更新

在本章中,我們將討論和學(xué)習(xí)PL/SQL中的異常。 程序執(zhí)行過程中的錯(cuò)誤情況是一個(gè)例外(異常)。 PL/SQL支持程序員在程序中使用EXCEPTION塊捕獲這些發(fā)生錯(cuò)誤的條件,并針對(duì)錯(cuò)誤情況采取適當(dāng)?shù)拇胧?。PL/SQL中有兩種異常 -

  • 系統(tǒng)定義的異常
  • 用戶定義的異常

異常處理的語法

異常處理的一般語法如下。在這里,可以列舉盡可能多的異常并且指定處理方式。默認(rèn)的異常將使用WHEN...THEN處理,如下語法所示 -

DECLARE 
   <declarations section> 
BEGIN 
   <executable command(s)> 
EXCEPTION 
   <exception handling goes here > 
   WHEN exception1 THEN  
      exception1-handling-statements  
   WHEN exception2  THEN  
      exception2-handling-statements  
   WHEN exception3 THEN  
      exception3-handling-statements 
   ........ 
   WHEN others THEN 
      exception3-handling-statements 
END;
SQL

示例

下面寫一個(gè)代碼來說明和理解這個(gè)概念,這里使用前面章節(jié)中創(chuàng)建和使用的CUSTOMERS表,結(jié)構(gòu)和數(shù)據(jù)如下 -

CREATE TABLE CUSTOMERS( 
   ID   INT NOT NULL, 
   NAME VARCHAR (20) NOT NULL, 
   AGE INT NOT NULL, 
   ADDRESS CHAR (25), 
   SALARY   DECIMAL (18, 2),        
   PRIMARY KEY (ID) 
);
-- 向CUSTOMERS表中插入一些數(shù)據(jù)記錄 
INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) 
VALUES (1, 'Ramesh', 32, 'Ahmedabad', 2000.00 );  

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) 
VALUES (2, 'Khilan', 25, 'Delhi', 1500.00 );  

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) 
VALUES (3, 'kaushik', 23, 'Kota', 2000.00 );

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) 
VALUES (4, 'Chaitali', 25, 'Mumbai', 6500.00 ); 

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) 
VALUES (5, 'Hardik', 27, 'Bhopal', 8500.00 );  

INSERT INTO CUSTOMERS (ID,NAME,AGE,ADDRESS,SALARY) 
VALUES (6, 'Komal', 22, 'MP', 4500.00 );
SQL

下面是一個(gè)未找到數(shù)據(jù)記錄時(shí)的異常處理 -

SET SERVEROUTPUT ON SIZE 99999;
DECLARE 
   c_id customers.id%type := 100; 
   c_name  customerS.name%type; 
   c_addr customers.address%type; 
BEGIN 
   SELECT  name, address INTO  c_name, c_addr 
   FROM customers 
   WHERE id = c_id;  
   DBMS_OUTPUT.PUT_LINE ('姓名: '||  c_name); 
   DBMS_OUTPUT.PUT_LINE ('地址: ' || c_addr); 

EXCEPTION 
   WHEN no_data_found THEN 
      dbms_output.put_line('沒有找到符合條件的客戶信息!'); 
   WHEN others THEN 
      dbms_output.put_line('Error!'); 
END; 
/
SQL

執(zhí)行上面示例代碼,得到以下結(jié)果 -


上面的程序用于顯示指定ID的客戶的名字和地址。但是由于數(shù)據(jù)庫customers表中并沒有ID值為100的客戶,因此程序引發(fā)異常,并在EXCEPTION塊中捕獲的運(yùn)行時(shí)異常NO_DATA_FOUND,因此最后打印了信息:‘沒有找到符合條件的客戶信息!’。

引發(fā)異常

只要有內(nèi)部數(shù)據(jù)庫錯(cuò)誤,數(shù)據(jù)庫服務(wù)器就會(huì)自動(dòng)產(chǎn)生(引發(fā))異常,但程序員可以使用命令RAISE明確地引發(fā)異常。以下是引發(fā)異常的簡單語法 -

DECLARE 
   exception_name EXCEPTION; 
BEGIN 
   IF condition THEN 
      RAISE exception_name; 
   END IF; 
EXCEPTION 
   WHEN exception_name THEN 
   statement; 
END;
SQL

可以使用上述語法來引發(fā)Oracle標(biāo)準(zhǔn)異?;蛉魏斡脩舳x的異常。 在下一節(jié)中,我們將舉例說明引發(fā)用戶定義的異常。您可以用類似的方式引發(fā)Oracle中標(biāo)準(zhǔn)異常。

用戶定義的異常

PL/SQL允許根據(jù)程序的需要定義自己的異常。 用戶定義的異常必須聲明,然后使用RAISE語句或過程DBMS_STANDARD.RAISE_APPLICATION_ERROR顯式地引發(fā)。

聲明異常的語法是 -

DECLARE 
   my-exception EXCEPTION;
SQL

示例

以下示例說明了這個(gè)概念。這個(gè)程序要求輸入一個(gè)客戶ID,當(dāng)用戶輸入一個(gè)無效的ID時(shí),會(huì)引發(fā)異常invalid_id。參考以下示例代碼的實(shí)現(xiàn) -

SET SERVEROUTPUT ON SIZE 9999;
DECLARE 
   c_id customers.id%type := &cc_id; 
   c_name  customerS.name%type; 
   c_addr customers.address%type;  
   -- user defined exception 
   ex_invalid_id  EXCEPTION; 
BEGIN 
   IF c_id <= 0 THEN 
      RAISE ex_invalid_id; 
   ELSE 
      SELECT  name, address INTO  c_name, c_addr 
      FROM customers 
      WHERE id = c_id;
      DBMS_OUTPUT.PUT_LINE ('姓名: '||  c_name);  
      DBMS_OUTPUT.PUT_LINE ('地址: ' || c_addr); 
   END IF; 

EXCEPTION 
   WHEN ex_invalid_id THEN 
      dbms_output.put_line('編號(hào)ID必須要大于0!'); 
   WHEN no_data_found THEN 
      dbms_output.put_line('未找到指定ID的客戶信息!'); 
   WHEN others THEN 
      dbms_output.put_line('Error!');  
END; 
/
SQL

執(zhí)行上面示例代碼,得到以下結(jié)果 -

輸入 cc_id 的值:  -1
原值    2:    c_id customers.id%type := &cc_id;
新值    2:    c_id customers.id%type := -1;
編號(hào)ID必須要大于0!

PL/SQL 過程已成功完成。
Shell

預(yù)定義的異常

PL/SQL提供了許多預(yù)定義的異常,這些異常在程序違反任何數(shù)據(jù)庫規(guī)則時(shí)執(zhí)行。 例如,當(dāng)SELECT INTO語句不返回任何行時(shí),會(huì)引發(fā)預(yù)定義的異常NO_DATA_FOUND。下表列出了一些重要的預(yù)定義異常情況 -

異常 Oracle錯(cuò)誤代碼 SQLCODE 描述
ACCESS_INTO_NULL 06530 -6530 當(dāng)一個(gè)空對(duì)象被自動(dòng)分配一個(gè)值時(shí)會(huì)引發(fā)它。
CASE_NOT_FOUND 06592 -6592 當(dāng)沒有選擇CASE語句的WHEN子句中的任何選項(xiàng)時(shí),會(huì)引發(fā)這個(gè)錯(cuò)誤,并且沒有ELSE子句。
COLLECTION_IS_NULL 06531 -6531 當(dāng)程序嘗試將EXISTS以外的集合方法應(yīng)用于未初始化的嵌套表或varray時(shí),或程序嘗試將值分配給未初始化的嵌套表或varray的元素時(shí),會(huì)引發(fā)此問題。
DUP_VAL_ON_INDEX 00001 -1 當(dāng)嘗試將重復(fù)值存儲(chǔ)在具有唯一索引的列中時(shí)引發(fā)此錯(cuò)誤。
INVALID_CURSOR 01001 -1001 當(dāng)嘗試進(jìn)行不允許的游標(biāo)操作(例如關(guān)閉未打開的游標(biāo))時(shí)會(huì)引發(fā)此錯(cuò)誤。
INVALID_NUMBER 01722 -1722 當(dāng)字符串轉(zhuǎn)換為數(shù)字時(shí)失敗,因?yàn)樽址淮碛行У臄?shù)字。
LOGIN_DENIED 01017 -1017 當(dāng)程序嘗試使用無效的用戶名或密碼登錄到數(shù)據(jù)庫時(shí)引發(fā)。
NO_DATA_FOUND 01403 +100 當(dāng)SELECT INTO語句不返回任何行時(shí)會(huì)引發(fā)它。
NOT_LOGGED_ON 01012 -1012 當(dāng)數(shù)據(jù)庫調(diào)用沒有連接到數(shù)據(jù)庫時(shí)引發(fā)。
PROGRAM_ERROR 06501 -6501 當(dāng)PL/SQL遇到內(nèi)部問題時(shí)會(huì)引發(fā)。
ROWTYPE_MISMATCH 06504 -6504 當(dāng)游標(biāo)在具有不兼容數(shù)據(jù)類型的變量中獲取值時(shí)引發(fā)。
SELF_IS_NULL 30625 -30625 當(dāng)調(diào)用成員方法時(shí)引發(fā),但對(duì)象類型的實(shí)例未初始化。
STORAGE_ERROR 06500 -6500 當(dāng)PL/SQL用盡內(nèi)存或內(nèi)存已損壞時(shí)引發(fā)。
TOO_MANY_ROWS 01422 -1422 當(dāng)SELECT INTO語句返回多行時(shí)引發(fā)。
VALUE_ERROR 06502 -6502 當(dāng)發(fā)生算術(shù),轉(zhuǎn)換,截?cái)嗷蛘?code>sizeconstraint錯(cuò)誤時(shí)引發(fā)。
ZERO_DIVIDE 01476 1476 當(dāng)嘗試將數(shù)字除以零時(shí)引發(fā)。




以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)