예외 사항 처리(런타임 오류)
PL/SQL 코드를 사용하여 런타임 시 발생하는 예외를 처리할 수 있습니다.
참조: PL/SQL 오류 처리에 대한 자세한 내용은 Oracle Database PL/SQL Language Reference를 참조하십시오
예외 사항 및 예외 사항 처리기
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를 참조하십시오.
-
EXCEPTION_INIT 프래그마에 대한 자세한 내용은 Oracle Database PL/SQL Language Reference를 참조하십시오
예외 처리기를 사용해야 하는 경우
다음 상황에서만 예외 처리기를 사용합니다.
-
예외를 예상하고 처리하려고 합니다.
예를 들어, 결국 SELECT INTO 문은 행을 반환하지 않으므로 Oracle Database에서 미리 정의된 예외 NO_DATA_FOUND를 발생시킬 것으로 예상합니다. Example 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에서는 미리 정의된 예외 사항 NO_DATA_FOUND를 처리하도록 EMP_EVAL.EVAL_DEPARTMENT 프로시저를 변경하는 방법을 보여 줍니다. 이 변경 작업을 수행하고 변경된 프로시저를 컴파일합니다. 패키지 본문을 변경하는 방법의 예제는 "자습서: 하위 프로그램에서 변수 및 상수 선언"을 참조하십시오.
예 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 함수를 변경하여 두 개의 사용자 정의 예외 사항 wrong_weight와 wrong_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에서 사용자 정의 예외에 대한 자세한 내용을 참조하십시오.