
- PL/SQL 教程
- PL/SQL - 首頁
- PL/SQL - 概述
- PL/SQL - 環境
- PL/SQL - 基本語法
- PL/SQL - 資料型別
- PL/SQL - 變數
- PL/SQL - 常量和字面量
- PL/SQL - 運算子
- PL/SQL - 條件
- PL/SQL - 迴圈
- PL/SQL - 字串
- PL/SQL - 陣列
- PL/SQL - 過程
- PL/SQL - 函式
- PL/SQL - 遊標
- PL/SQL - 記錄
- PL/SQL - 異常
- PL/SQL - 觸發器
- PL/SQL - 包
- PL/SQL - 集合
- PL/SQL - 事務
- PL/SQL - 日期和時間
- PL/SQL - DBMS 輸出
- PL/SQL - 面向物件
- PL/SQL 有用資源
- PL/SQL - 問題和解答
- PL/SQL - 快速指南
- PL/SQL - 有用資源
- PL/SQL - 討論
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 | 當嘗試將數字除以零時引發。 |