位置:首頁 > 數據庫 > PL/SQL教學 > PL/SQL異常

PL/SQL異常

程序執行過程中出現錯誤情況被稱為在PL/SQL異常。 PL/SQL支持程序員在程序中使用異常塊捕獲這樣的條件並采取適當的動作應對錯誤情況。有兩種類型的異常:

  • 係統定義的異常

  • 用戶定義的異常

異常處理語法

一般異常處理的語法如下。在這裡可以列出下來很多,要處理異常。默認的異常將使用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提供許多預先定義的異常,這是在被執行時的任何數據庫規則由程序引發。例如,預定義異常NO_DATA_FOUND時引發一個SELECT INTO語句返回數據行。下表列出了一些重要的預先定義的異常:

Exception Oracle Error SQLCODE 描述
ACCESS_INTO_NULL 06530 -6530 當一個空對象會自動分配一個值引發此異常
CASE_NOT_FOUND 06592 -6592 當冇有任何選擇,在當選擇一個CASE語句的子句,並且冇有ELSE子句時被引發
COLLECTION_IS_NULL 06531 -6531 當程序試圖申請其他收集方法不是存在未初始化的嵌套表或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 它被引發當一個數試圖除以零。