PL/SQL異常處理

在本章中,我們將討論和學習PL/SQL中的異常。 程式執行過程中的錯誤情況是一個例外(異常)。 PL/SQL支持程式員在程式中使用EXCEPTION塊捕獲這些發生錯誤的條件,並針對錯誤情況採取適當的措施。PL/SQL中有兩種異常 -

  • 系統定義的異常
  • 用戶定義的異常

異常處理的語法

異常處理的一般語法如下。在這裏,可以列舉盡可能多的異常並且指定處理方式。默認的異常將使用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;

示例

下麵寫一個代碼來說明和理解這個概念,這裏使用前面章節中創建和使用的CUSTOMERS表,結構和數據如下 -

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表中插入一些數據記錄

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 );

下麵是一個未找到數據記錄時的異常處理 -

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;
/

執行上面示例代碼,得到以下結果 -

上面的程式用於顯示指定ID的客戶的名字和地址。但是由於資料庫customers表中並沒有ID值為100的客戶,因此程式引發異常,並在EXCEPTION塊中捕獲的運行時異常NO_DATA_FOUND,因此最後列印了資訊:‘沒有找到符合條件的客戶資訊!’

引發異常

只要有內部資料庫錯誤,資料庫伺服器就會自動產生(引發)異常,但程式員可以使用命令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。參考以下示例代碼的實現 -

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('編號ID必須要大於0!');
   WHEN no_data_found THEN
      dbms_output.put_line('未找到指定ID的客戶資訊!');
   WHEN others THEN
      dbms_output.put_line('Error!');
END;
/

執行上面示例代碼,得到以下結果 -

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

PL/SQL 過程已成功完成。

預定義的異常

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 當程式嘗試將EXISTS以外的集合方法應用於未初始化的嵌套表或varray時,或程式嘗試將值分配給未初始化的嵌套表或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 當發生算術,轉換,截斷或者sizeconstraint錯誤時引發。
ZERO_DIVIDE 01476 1476 當嘗試將數字除以零時引發。

上一篇: PL/SQL記錄 下一篇: PL/SQL觸發器