處理例外情況 (執行時期錯誤)

您可以使用 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 錯誤號碼相關聯。

另請參閱:

使用例外情況處理程式的時機

僅在下列情況下使用例外情況處理常式。

處理預先定義的異常狀況

您可以處理預先定義的例外情況。範例 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,瞭解有關使用者定義之異常狀況的詳細資訊