- 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 | 當嘗試將數字除以零時引發。 |