예외 처리 Oracle PL/SQL(예제)
⚡ 스마트 요약
예외 처리 Oracle PL/SQL은 블록 실행을 중단시키는 런타임 오류를 포착하여 엔진이 제어권을 EXCEPTION 섹션으로 넘길 수 있도록 합니다. EXCEPTION 섹션에서는 미리 정의된 핸들러, 사용자 정의 핸들러 및 기타 핸들러가 오류에 안전하게 대응하거나, 오류를 발생시키거나, 오류를 전파할 수 있습니다.

PL/SQL의 예외 처리란 무엇입니까?
PL/SQL 엔진이 런타임 오류로 인해 실행할 수 없는 명령어를 만났을 때 예외가 발생합니다. 이러한 오류는 컴파일 시간에는 감지되지 않으므로 런타임에만 처리해야 합니다.
예를 들어, PL/SQL 엔진이 0으로 나누라는 명령을 받으면 예외를 발생시켜 오류를 처리합니다. 이 예외는 PL/SQL 엔진에서 런타임 시에만 발생합니다.
예외가 발생하면 프로그램의 실행이 중단되므로, 이러한 상황을 방지하기 위해서는 오류를 포착하여 별도로 처리해야 합니다. 이 과정을 예외 처리라고 하며, 프로그래머는 실행 중에 발생할 수 있는 오류를 처리합니다.
예외 처리 구문
예외는 블록 수준에서 처리됩니다. 블록 내에서 예외가 발생하면 제어는 해당 블록의 실행 부분을 벗어나 블록의 예외 처리 부분에서 예외를 처리합니다. 예외 처리가 완료된 후에는 제어가 해당 블록의 실행 부분으로 다시 돌아갈 수 없습니다.
아래 그림은 실행 부분과 예외 처리 부분이 하나의 PL/SQL 블록 내에 어떻게 위치하는지 보여줍니다.
아래 구문은 예외를 포착하고 처리하는 방법을 설명합니다.
BEGIN <execution block> . . EXCEPTION WHEN <exceptionl_name> THEN <Exception handling code for the “exception 1 _name’' > WHEN OTHERS THEN <Default exception handling code for all exceptions > END;
구문 설명:
- 위 구문에서 예외 처리 블록은 예외를 처리하기 위한 일련의 WHEN 조건을 포함합니다.
- 각 WHEN 조건 뒤에는 런타임에 발생할 것으로 예상되는 예외 이름이 옵니다.
- 실행 중에 예외가 발생하면 PL/SQL 엔진은 첫 번째 WHEN 절부터 순차적으로 이동하면서 예외 처리 부분에서 해당 예외를 검색합니다.
- 발생한 예외에 대한 핸들러를 찾으면 해당 핸들러 코드를 실행합니다.
- 발생한 예외와 일치하는 WHEN 절이 없으면 PL/SQL 엔진은 WHEN OTHERS 부분이 있는 경우 해당 부분을 실행합니다. 이 핸들러는 모든 예외에 공통으로 적용됩니다.
- 핸들러가 실행된 후 제어권은 현재 블록에서 벗어납니다.
- 실행 시점에 블록당 하나의 예외 처리기만 실행될 수 있습니다. 해당 예외 처리기가 실행되면 엔진은 나머지 처리기를 건너뛰고 현재 블록을 종료합니다.
참고 : `WHEN OTHERS`는 항상 코드 순서의 맨 마지막에 위치해야 합니다. `WHEN OTHERS` 이후에 작성된 핸들러는 실행되지 않습니다. `WHEN OTHERS`가 실행되면 제어 흐름이 블록에서 벗어나기 때문입니다.
예외 유형
예외에는 두 가지 유형이 있습니다. PL / SQL.
- 미리 정의된 예외
- 사용자 정의 예외
사전 정의된 예외
Oracle 몇 가지 일반적인 예외 사항이 미리 정의되어 있습니다. 각 미리 정의된 예외 사항은 고유한 이름과 오류 번호를 가지고 있으며, 모두 STANDARD 패키지에 선언되어 있습니다. Oracle코드에서는 이러한 미리 정의된 예외 이름을 직접 사용하여 해당 오류를 처리할 수 있습니다. 이러한 예외 이름 중 상당수는 일반적인 예외에 직접 대응됩니다. SQL 매일 마주치는 오류들.
다음은 미리 정의된 몇 가지 예외 사항입니다.
| 예외 | 오류 Code | 예외사유 |
|---|---|---|
| ACCESS_INTO_NULL | ORA-06530 | 초기화되지 않은 객체의 속성에 값을 할당하기 |
| CASE_NOT_FOUND | ORA-06592 | CASE 문의 WHEN 절 중 어느 것도 충족되지 않았고 ELSE 절도 지정되지 않았습니다. |
| COLLECTION_IS_NULL | ORA-06531 | 초기화되지 않은 컬렉션에서 컬렉션 메서드(EXISTS 제외)를 사용하거나 컬렉션 속성에 접근하는 행위 |
| CURSOR_ALREADY_OPEN | ORA-06511 | 열려고하는 중 커서 이미 열려 있습니다 |
| DUP_VAL_ON_INDEX | ORA-00001 | 고유 인덱스로 제한된 데이터베이스 열에 중복 값을 저장하는 것 |
| INVALID_CURSOR | ORA-01001 | 열리지 않은 커서를 닫는 것과 같은 잘못된 커서 조작 |
| 잘못된 번호 | ORA-01722 | 잘못된 숫자 문자로 인해 문자를 숫자로 변환하는 데 실패했습니다. |
| 데이터가 없습니다 | ORA-01403 | INTO 절이 포함된 SELECT 문은 행을 가져오지 않습니다. |
| ROW_MISMATCH | ORA-06504 | 커서 변수의 데이터 형식이 실제 커서 반환 형식과 호환되지 않습니다. |
| SUBSCRIPT_BEYOND_COUNT명 | ORA-06533 | 컬렉션 크기보다 큰 색인 번호로 컬렉션을 참조하는 것 |
| SUBSCRIPT_OUTSIDE_LIMIT | ORA-06532 | 허용되는 범위를 벗어난 색인 번호(예: -1)로 컬렉션을 참조하는 경우 |
| TOO_MANY_ROWS | ORA-01422 | INTO 절이 포함된 SELECT 문은 두 개 이상의 행을 반환합니다. |
| VALUE_ERROR | ORA-06502 | 산술 오류 또는 크기 제약 조건 오류(예: 변수 크기보다 큰 값을 할당하는 경우) |
| ZERO_DIVIDE | ORA-01476 | 어떤 수를 0으로 나누기 |
사용자 정의 예외
위에서 설명한 미리 정의된 예외 외에도 프로그래머는 사용자 정의 예외를 생성하고 처리할 수 있습니다. 이러한 예외는 서브프로그램 수준의 선언 부분에서 생성되며 해당 서브프로그램 내부에서만 접근할 수 있습니다. 패키지 명세에 정의된 예외는 공개 예외이며 해당 패키지에 접근할 수 있는 모든 곳에서 접근할 수 있습니다.
구문: 서브프로그램 수준에서
DECLARE <exception_name> EXCEPTION; BEGIN <Execution block> EXCEPTION WHEN <exception_name> THEN <Handler> END;
- 위 구문에서 변수 'exception_name'은 EXCEPTION 유형으로 정의됩니다.
- 그러면 미리 정의된 예외와 동일한 방식으로 사용할 수 있습니다.
구문: 패키지 명세 수준에서
CREATE PACKAGE <package_name> IS <exception_name> EXCEPTION; . . END <package_name>;
- 위 구문에서 변수 'exception_name'은 패키지 명세에서 EXCEPTION 유형으로 정의됩니다. .
- 이 기능은 'package_name' 패키지를 호출할 수 있는 데이터베이스 내 모든 곳에서 사용할 수 있습니다.
PL/SQL 발생 예외
미리 정의된 예외는 해당 오류가 발생할 때마다 암묵적으로 발생합니다. 그러나 사용자 정의 예외는 RAISE 키워드를 사용하여 명시적으로 발생시켜야 합니다. RAISE는 아래와 같은 방식으로 사용할 수 있습니다.
핸들러 내부에서 RAISE를 단독으로 사용하면 이미 발생한 예외가 상위 블록으로 전파됩니다. 아래와 같이 예외 블록 내부에서만 사용할 수 있습니다.
아래 스크린샷은 RAISE 문을 단독으로 사용하여 상위 블록에 예외를 다시 발생시키는 방법을 보여줍니다.
CREATE [ PROCEDURE | FUNCTION ] AS BEGIN <Execution block> EXCEPTION WHEN <exception_name> THEN <Handler> RAISE; END;
구문 설명:
- 위 구문에서 RAISE 키워드는 예외 처리 블록 내부에 사용됩니다.
- 프로그램이 'exception_name'이라는 예외를 만나면 해당 예외가 처리되고 정상적으로 완료됩니다.
- 핸들러의 RAISE 키워드는 해당 예외를 상위 프로그램으로 전파합니다.
참고 : 부모 블록에 예외를 발생시킬 때는 발생하는 예외가 부모 블록에서도 보여야 합니다. 그렇지 않으면 Oracle 오류가 발생합니다.
또한, RAISE 키워드 뒤에 예외 이름을 사용하여 특정 사용자 정의 또는 사전 정의된 예외를 발생시킬 수 있습니다. 이 형식은 실행 부분과 예외 처리 부분 모두에서 사용할 수 있습니다.
아래 스크린샷은 특정 예외를 발생시키기 위해 RAISE 명령어 다음에 예외 이름을 입력하는 방법을 보여줍니다.
CREATE [ PROCEDURE | FUNCTION ] AS BEGIN <Execution block> RAISE <exception_name> EXCEPTION WHEN <exception_name> THEN <Handler> END;
구문 설명:
- 위 구문에서 실행 부분에는 RAISE 키워드가 사용되고 그 뒤에 예외 'exception_name'이 옵니다.
- 이로 인해 런타임에 특정 예외가 발생하며, 해당 예외는 처리되거나 추가적으로 처리되어야 합니다.
예 1 : 이 예시에서는 다음과 같은 내용을 볼 수 있습니다.
- 예외를 선언하는 방법
- 선언된 예외를 발생시키는 방법
- 메인 블록에 전파하는 방법
아래 스크린샷은 sample_exception을 선언하고, 중첩된 블록 내부에서 예외를 발생시키고, 이를 메인 블록으로 전파하는 전체 코드 블록을 보여줍니다.
다음 스크린샷은 동일한 예제가 계속되는 모습을 보여주며, 메인 블록이 전파된 예외를 최종적으로 포착합니다.
DECLARE Sample_exception EXCEPTION; PROCEDURE nested_block IS BEGIN Dbms_output.put_line('Inside nested block'); Dbms_output.put_line('Raising sample_exception from nested block'); RAISE sample_exception; EXCEPTION WHEN sample_exception THEN Dbms_output.put_line ('Exception captured in nested block. Raising to main block'); RAISE; END; BEGIN Dbms_output.put_line('Inside main block'); Dbms_output.put_line('Calling nested block'); Nested_block; EXCEPTION WHEN sample_exception THEN Dbms_output.put_line ('Exception captured in main block'); END; /
Code 설명 :
- Code 2행: 변수 'sample_exception'을 EXCEPTION 유형으로 선언합니다.
- Code 3행: nested_block 프로시저를 선언합니다.
- Code 6행: "중첩 블록 내부"라는 문구를 출력합니다.
- Code 7행: "중첩 블록에서 sample_exception 발생"이라는 메시지를 출력합니다.
- Code 8행: 'RAISE Sample_Exception'을 사용하여 예외를 발생시킵니다.
- Code 10행: 중첩 블록 내의 sample_exception 예외에 대한 예외 처리기입니다.
- Code 11행: "중첩 블록에서 예외가 발생했습니다. 메인 블록으로 예외를 발생시킵니다."라는 메시지를 출력합니다.
- Code 12행: 메인 블록에 예외를 발생시킵니다(예외를 전파합니다).
- Code 15행: "메인 블록 내부"라는 문구를 출력합니다.
- Code 16행: "내포된 블록 호출" 명령문을 인쇄합니다.
- Code 17행: nested_block 프로시저를 호출합니다.
- Code 19행: 메인 블록의 Sample_Exception에 대한 예외 처리기입니다.
- Code 20행: "메인 블록에서 예외가 발생했습니다."라는 메시지를 출력합니다.
Exception에서 주의할 중요한 사항
- 함수 내에서 예외가 발생하면 항상 값을 반환하거나 예외를 추가로 발생시켜야 합니다. 그렇지 않으면 문제가 발생합니다. Oracle 실행 시 '함수가 값을 반환하지 않았습니다'라는 오류가 발생합니다.
- 거래 통제 명세서 예외 처리 블록 내에서 발행될 수 있습니다.
- SQLERRM과 SQLCODE는 각각 예외 메시지와 예외 코드를 반환하는 내장 함수입니다.
- 예외가 처리되지 않으면 기본적으로 해당 세션의 모든 활성 트랜잭션이 롤백됩니다.
- RAISE_APPLICATION_ERROR(- , `RAISE` 대신 `__error__`를 사용하여 사용자 지정 오류 코드와 메시지를 포함한 오류를 발생시킬 수 있습니다. 오류 코드는 -20000에서 -20999 사이여야 합니다.





