14. PL/SQL異常(Exception)

程式執行過程中出現錯誤情況被稱為在PL/SQL異常(Exception)。 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;
/


範例

寫一些簡單的程式來說明這個概念。(範例Table)
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;
/


結果如下:
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;
/


使用者自定義異常

PL/SQL允許根據程式的需要定義自己的異常。定義的異常必須宣告,然後明確地提出使用一個RAISE語法或程序DBMS_STANDARD.RAISE_APPLICATION_ERROR。
宣告一個異常的語法是:
DECLARE
  my-exception EXCEPTION;


範例:

下面的例子說明了這個概念。當使用者輸入了一個無效的ID,異常invalid_id引發。(範例table)
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;
/
結果如下:
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
它被引發當一個數試圖除以零。

沒有留言:

張貼留言