處理例外情況 (執行時期錯誤)
您可以使用 PL/SQL 程式碼來處理在程式實際執行時發生的異常狀況。
另請參閱:Oracle Database PL/SQL Language Reference,瞭解有關處理 PL/SQL 錯誤的詳細資訊
關於異常狀況和異常狀況處理程式
當 PL/SQL 程式碼發生程式實際執行錯誤,會發生異常狀況。如果發生例外的次程式 (或區塊) 具有例外處理部份,則控制會傳輸至該程式;否則,會停止執行。
程式實際執行錯誤可能是由於設計錯誤、編碼錯誤、硬體故障以及許多其他來源所產生。
Oracle Database 有許多預先定義的異常狀況,它會在程式違反資料庫規則或超過系統相依限制時自動發出。例如,如果 SELECT INTO 敘述句未傳回任何資料列,Oracle Database 就會發出預先定義的異常狀況 NO_DATA_FOUND。有關預先定義的 PL/SQL 例外摘要,請參閱 Oracle Database PL/SQL Language Reference。
PL/SQL 可讓您定義 (宣告) 自己的異常狀況。異常狀況宣告具有以下語法:
exception_name EXCEPTION;
與預先定義的例外不同,必須使用 RAISE 陳述式或 DBMS_STANDARD.RAISE_APPLICATION_ERROR 程序明確產生使用者定義的例外。舉例而言:
IF condition THEN RAISE exception_name;
如需有關 DBMS_STANDARD.RAISE_APPLICATION_ERROR 程序的資訊,請參閱 Oracle Database PL/SQL Language Reference。
子程式的異常狀況處理部分包含一或多個異常狀況處理程式。例外處理程式具有下列語法:
WHEN { exception_name [ OR exception_name ]... | OTHERS } THEN
statement; [ statement; ]...
(「關於子程式結構」顯示放置子程式之異常狀況處理的位置。)
WHEN OTHERS 例外處理程式處理非預期的執行時期錯誤。若要使用,它必須放在最後,例如:舉例而言:
EXCEPTION
WHEN exception_1 THEN
statement; [ statement; ]...
WHEN exception_2 OR exception_3 THEN
statement; [ statement; ]...
WHEN OTHERS THEN
statement; [ statement; ]...
RAISE; -- Reraise the exception (very important).
END;
WHEN OTHERS 例外情況處理程式的替代方法,就是 EXCEPTION_INIT 編譯法,此編譯法會將使用者定義的例外情況名稱與 Oracle Database 錯誤號碼相關聯。
另請參閱:
-
Oracle Database PL/SQL Language Reference,瞭解異常狀況宣告語法的詳細資訊
-
Oracle Database PL/SQL Language Reference,瞭解異常狀況處理程式語法的詳細資訊
-
Oracle Database PL/SQL Language Reference,瞭解 EXCEPTION_INIT 編譯描述的詳細資訊
使用例外情況處理程式的時機
僅在下列情況下使用例外情況處理常式。
-
您預期會發生異常狀況,而且想要加以處理。
例如,您預期 SELECT INTO 敘述句最終不會傳回任何資料列,因此 Oracle Database 會發出預先定義的異常狀況 NO_DATA_FOUND。您希望您的子程式或區塊處理該異常狀況 (不是錯誤),然後繼續進行,如範例 5-13 中所示。
-
您必須重新取得或關閉資源,如下列範例所示。
... file := UTL_FILE.OPEN ... BEGIN statement statement]... -- If this code fails for any reason, EXCEPTION WHEN OTHERS THEN UTL_FILE.FCLOSE(file); -- then you want to close the file. RAISE; -- Reraise the exception (very important). END; UTL_FILE.FCLOSE(file); ... -
在程式碼的最上層,記錄錯誤。
例如,從屬端處理作業可能會發出此區塊:
BEGIN proc(...); EXCEPTION WHEN OTHERS THEN log_error_using_autonomous_transaction(...); RAISE; -- Reraise the exception (very important). END; /或者,用戶端所呼叫的獨立子程式可以包含相同的例外情況處理邏輯,但只能在最上層。
處理預先定義的異常狀況
您可以處理預先定義的例外情況。範例 5-13 顯示如何變更 EMP_EVAL.EVAL_DEPARTMENT 程序,以處理預先定義的例外 NO_DATA_FOUND。進行此變更並編譯已變更的程序。(如需如何變更套件主體的範例,請參閱「教學課程:在子程式中宣告變數與常數」。)
範例 5-13 處理預先定義的異常狀況 NO_DATA_FOUND
PROCEDURE eval_department(dept_id IN employees.department_id%TYPE) AS
emp_cursor emp_refcursor_type;
current_dept departments.department_id%TYPE;
BEGIN
current_dept := dept_id;
FOR loop_c IN 1..3 LOOP
OPEN emp_cursor FOR
SELECT *
FROM employees
WHERE current_dept = eval_department.dept_id;
DBMS_OUTPUT.PUT_LINE
('Determining necessary evaluations in department #' ||
current_dept);
eval_loop_control(emp_cursor);
DBMS_OUTPUT.PUT_LINE
('Processed ' || emp_cursor%ROWCOUNT || ' records.');
CLOSE emp_cursor;
current_dept := current_dept + 10;
END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE ('The query did not return a result set');
END eval_department;
另請參閱:Oracle Database PL/SQL Language Reference,瞭解有關預先定義之異常狀況的詳細資訊
宣告及處理使用者定義的異常狀況
您可以宣告和處理使用者定義的異常狀況。範例 5-14 顯示如何變更 EMP_EVAL.CALCULATE_SCORE 函數,以宣告和處理兩個使用者定義的異常狀況:error_weight 和 error_score。進行此變更並編譯已變更的函數。(如需如何變更套件主體的範例,請參閱「教學課程:在子程式中宣告變數與常數」。)
範例 5-14 處理使用者定義的異常狀況
FUNCTION calculate_score ( evaluation_id IN scores.evaluation_id%TYPE
, performance_id IN scores.performance_id%TYPE )
RETURN NUMBER AS
weight_wrong EXCEPTION;
score_wrong EXCEPTION;
n_score scores.score%TYPE;
n_weight performance_parts.weight%TYPE;
running_total NUMBER := 0;
max_score CONSTANT scores.score%TYPE := 9;
max_weight CONSTANT performance_parts.weight%TYPE:= 1;
BEGIN
SELECT s.score INTO n_score
FROM SCORES s
WHERE evaluation_id = s.evaluation_id
AND performance_id = s.performance_id;
SELECT p.weight INTO n_weight
FROM PERFORMANCE_PARTS p
WHERE performance_id = p.performance_id;
BEGIN
IF (n_weight > max_weight) OR (n_weight < 0) THEN
RAISE weight_wrong;
END IF;
END;
BEGIN
IF (n_score > max_score) OR (n_score < 0) THEN
RAISE score_wrong;
END IF;
END;
running_total := n_score * n_weight;
RETURN running_total;
EXCEPTION
WHEN weight_wrong THEN
DBMS_OUTPUT.PUT_LINE(
'The weight of a score must be between 0 and ' || max_weight);
RETURN -1;
WHEN score_wrong THEN
DBMS_OUTPUT.PUT_LINE(
'The score must be between 0 and ' || max_score);
RETURN -1;
END calculate_score;
另請參閱:Oracle Database PL/SQL Language Reference,瞭解有關使用者定義之異常狀況的詳細資訊