PL/SQL - 異常



在本章中,我們將討論 PL/SQL 中的異常。異常是在程式執行期間發生的錯誤條件。PL/SQL 支援程式設計師使用程式中的EXCEPTION塊捕獲此類條件,並對錯誤條件採取適當的措施。異常有兩種型別:

  • 系統定義的異常
  • 使用者定義的異常

異常處理的語法

異常處理的通用語法如下。您可以在此處列出儘可能多的要處理的異常。預設異常將使用WHEN others 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;

示例

讓我們編寫一段程式碼來說明這個概念。我們將使用我們在前幾章建立和使用的 CUSTOMERS 表:

DECLARE 
   c_id customers.id%type := 8; 
   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 ('Name: '||  c_name); 
   DBMS_OUTPUT.PUT_LINE ('Address: ' || c_addr); 

EXCEPTION 
   WHEN no_data_found THEN 
      dbms_output.put_line('No such customer!'); 
   WHEN others THEN 
      dbms_output.put_line('Error!'); 
END; 
/

當以上程式碼在 SQL 提示符下執行時,它會產生以下結果:

No such customer!  

PL/SQL procedure successfully completed. 

以上程式顯示了給定 ID 的客戶的姓名和地址。由於我們的資料庫中沒有 ID 值為 8 的客戶,因此程式引發了執行時異常NO_DATA_FOUND,該異常在EXCEPTION 塊中被捕獲。

引發異常

每當出現任何內部資料庫錯誤時,資料庫伺服器都會自動引發異常,但程式設計師可以使用命令RAISE顯式引發異常。以下是引發異常的簡單語法:

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

您可以使用以上語法引發 Oracle 標準異常或任何使用者定義的異常。在下一節中,我們將為您提供有關引發使用者定義異常的示例。您可以以類似的方式引發 Oracle 標準異常。

使用者定義的異常

PL/SQL 允許您根據程式的需要定義自己的異常。使用者定義的異常必須先宣告,然後才能使用 RAISE 語句或過程DBMS_STANDARD.RAISE_APPLICATION_ERROR顯式引發。

宣告異常的語法為:

DECLARE 
   my-exception EXCEPTION; 

示例

以下示例說明了此概念。此程式要求輸入客戶 ID,當用戶輸入無效 ID 時,將引發異常invalid_id

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 ('Name: '||  c_name);  
      DBMS_OUTPUT.PUT_LINE ('Address: ' || c_addr); 
   END IF; 

EXCEPTION 
   WHEN ex_invalid_id THEN 
      dbms_output.put_line('ID must be greater than zero!'); 
   WHEN no_data_found THEN 
      dbms_output.put_line('No such customer!'); 
   WHEN others THEN 
      dbms_output.put_line('Error!');  
END; 
/

當以上程式碼在 SQL 提示符下執行時,它會產生以下結果:

Enter value for cc_id: -6 (let's enter a value -6) 
old  2: c_id customers.id%type := &cc_id; 
new  2: c_id customers.id%type := -6; 
ID must be greater than zero! 
 
PL/SQL procedure successfully completed. 

預定義異常

PL/SQL 提供了許多預定義異常,當程式違反任何資料庫規則時,這些異常就會執行。例如,當 SELECT INTO 語句不返回任何行時,會引發預定義異常 NO_DATA_FOUND。下表列出了一些重要的預定義異常:

異常 Oracle 錯誤 SQLCODE 描述
ACCESS_INTO_NULL 06530 -6530 當空物件自動分配值時引發。
CASE_NOT_FOUND 06592 -6592 當 CASE 語句的 WHEN 子句中沒有選擇任何選項並且沒有 ELSE 子句時引發。
COLLECTION_IS_NULL 06531 -6531 當程式嘗試對未初始化的巢狀表或 varray 應用除 EXISTS 之外的集合方法,或程式嘗試為未初始化的巢狀表或 varray 的元素賦值時引發。
DUP_VAL_ON_INDEX 00001 -1 當嘗試在具有唯一索引的列中儲存重複值時引發。
INVALID_CURSOR 01001 -1001 當嘗試執行不允許的遊標操作(例如關閉未開啟的遊標)時引發。
INVALID_NUMBER 01722 -1722 當字元字串轉換為數字失敗,因為該字串不表示有效的數字時引發。
LOGIN_DENIED 01017 -1017 當程式嘗試使用無效使用者名稱或密碼登入資料庫時引發。
NO_DATA_FOUND 01403 +100 當 SELECT INTO 語句不返回任何行時引發。
NOT_LOGGED_ON 01012 -1012 當在未連線到資料庫的情況下發出資料庫呼叫時引發。
PROGRAM_ERROR 06501 -6501 當 PL/SQL 出現內部問題時引發。
ROWTYPE_MISMATCH 06504 -6504 當遊標在具有不相容資料型別的變數中獲取值時引發。
SELF_IS_NULL 30625 -30625 當呼叫成員方法但未初始化物件型別的例項時引發。
STORAGE_ERROR 06500 -6500 當 PL/SQL 記憶體不足或記憶體損壞時引發。
TOO_MANY_ROWS 01422 -1422 當 SELECT INTO 語句返回多行時引發。
VALUE_ERROR 06502 -6502 當發生算術、轉換、截斷或大小約束錯誤時引發。
ZERO_DIVIDE 01476 1476 當嘗試將數字除以零時引發。
廣告