예외 처리 Oracle PL/SQL(예제)

⚡ 스마트 요약

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

  • ⚙️ 실행 오류: PL/SQL 엔진이 0으로 나누기와 같이 실행할 수 없는 명령어를 만났을 때 예외가 발생합니다.
  • 🧱 블록 구조: 예외는 WHEN 절을 사용하여 EXCEPTION 섹션에서 처리하며, WHEN OTHERS는 항상 마지막에 배치됩니다.
  • 📚 사전 정의된 예외: Oracle STANDARD 패키지에서 흔히 발생하는 오류(예: NO_DATA_FOUND 및 ZERO_DIVIDE)를 직접 처리할 수 있도록 이름을 지정합니다.
  • 🛠️ 사용자 정의 예외: 프로그래머는 자체적으로 예외 변수를 선언하고 RAISE 키워드를 사용하여 명시적으로 예외를 발생시킵니다.
  • 번식: 처리되지 않은 예외는 상위 블록으로 전달되고, RAISE는 이를 상위 프로그램에 다시 알립니다.
  • 🤖 AI 지원: AI 코딩 도구는 검토 과정에서 예외 블록을 생성하고 처리되지 않은 오류 경로를 표시합니다.

예외 처리 Oracle PL / SQL

PL/SQL의 예외 처리란 무엇입니까?

PL/SQL 엔진이 런타임 오류로 인해 실행할 수 없는 명령어를 만났을 때 예외가 발생합니다. 이러한 오류는 컴파일 시간에는 감지되지 않으므로 런타임에만 처리해야 합니다.

예를 들어, PL/SQL 엔진이 0으로 나누라는 명령을 받으면 예외를 발생시켜 오류를 처리합니다. 이 예외는 PL/SQL 엔진에서 런타임 시에만 발생합니다.

예외가 발생하면 프로그램의 실행이 중단되므로, 이러한 상황을 방지하기 위해서는 오류를 포착하여 별도로 처리해야 합니다. 이 과정을 예외 처리라고 하며, 프로그래머는 실행 중에 발생할 수 있는 오류를 처리합니다.

예외 처리 구문

예외는 블록 수준에서 처리됩니다. 블록 내에서 예외가 발생하면 제어는 해당 블록의 실행 부분을 벗어나 블록의 예외 처리 부분에서 예외를 처리합니다. 예외 처리가 완료된 후에는 제어가 해당 블록의 실행 부분으로 다시 돌아갈 수 없습니다.

아래 그림은 실행 부분과 예외 처리 부분이 하나의 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 문을 단독으로 사용하여 상위 블록에 예외를 다시 발생시키는 방법을 보여줍니다.

RAISE 문만으로 예외를 상위 블록으로 전파합니다.

CREATE [ PROCEDURE | FUNCTION ]
 AS
BEGIN
<Execution block>
EXCEPTION
WHEN <exception_name> THEN
             <Handler>
RAISE;
END;

구문 설명:

  • 위 구문에서 RAISE 키워드는 예외 처리 블록 내부에 사용됩니다.
  • 프로그램이 'exception_name'이라는 예외를 만나면 해당 예외가 처리되고 정상적으로 완료됩니다.
  • 핸들러의 RAISE 키워드는 해당 예외를 상위 프로그램으로 전파합니다.

참고 : 부모 블록에 예외를 발생시킬 때는 발생하는 예외가 부모 블록에서도 보여야 합니다. 그렇지 않으면 Oracle 오류가 발생합니다.

또한, RAISE 키워드 뒤에 예외 이름을 사용하여 특정 사용자 정의 또는 사전 정의된 예외를 발생시킬 수 있습니다. 이 형식은 실행 부분과 예외 처리 부분 모두에서 사용할 수 있습니다.

아래 스크린샷은 특정 예외를 발생시키기 위해 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을 선언하고, 중첩된 블록 내부에서 예외를 발생시키고, 이를 메인 블록으로 전파하는 전체 코드 블록을 보여줍니다.

중첩 블록 내에서 사용자 정의 예외를 선언하고 발생시키는 PL/SQL 예제

다음 스크린샷은 동일한 예제가 계속되는 모습을 보여주며, 메인 블록이 전파된 예외를 최종적으로 포착합니다.

중첩 블록에서 먼저 포착된 예외와 그 다음 메인 블록에서 포착된 예외를 보여주는 출력입니다.

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 사이여야 합니다.

자주 묻는 질문

PRAGMA EXCEPTION_INIT는 사용자가 선언한 예외 이름을 특정 예외와 연결합니다. Oracle 오류 번호입니다. 바인딩 후, WHEN OTHERS를 사용하고 SQLCODE를 확인하는 대신 WHEN 절에서 이름으로 ORA 오류를 포착할 수 있습니다.

SQLCODE는 현재 예외의 숫자 오류 코드를 반환하고, SQLERRM은 텍스트 메시지를 반환합니다. 두 함수 모두 예외 처리기, 특히 WHEN OTHERS 블록 내에서 호출되어 오류 발생 원인을 기록하거나 표시합니다.

모든 오류를 묵묵히 무시하는 WHEN OTHERS 구문은 피하십시오. SQLCODE와 SQLERRM을 로깅하거나 RAISE를 사용하여 예외를 다시 발생시키지 않으면 버그가 은폐됩니다. WHEN OTHERS는 예외를 로깅하고, 정리하고, 전파하는 용도로만 사용하십시오.

RAISE_APPLICATION_ERROR는 -20000에서 -20999 사이의 오류 번호와 최대 2048바이트의 메시지를 허용합니다. 이 함수는 실행을 중지하고 호출하는 애플리케이션에 사용자 정의 오류를 반환하여 사용자 정의 조건을 기본 오류처럼 보이게 합니다. Oracle 오류.

같은 블록 안에 있으면 안 됩니다. 제어가 EXCEPTION 섹션으로 이동하면 해당 블록이 종료됩니다. 계속 실행하려면 위험한 구문을 BEGIN…EXCEPTION…END 블록으로 감싸야 합니다. 그러면 외부 블록이 오류를 처리한 후에도 계속 실행됩니다.

오류는 코드 실행 중 또는 컴파일 중에 발생하는 모든 문제를 의미합니다. 예외는 PL/SQL 런타임 메커니즘으로, 런타임 오류를 나타내며 프로그램이 갑자기 종료되는 대신 응답할 수 있도록 제어권을 EXCEPTION 섹션으로 전달합니다.

네. AI 비서와 머신러닝 기반 코드 검토자는 예외 블록을 작성하고, 처리할 사전 정의된 예외를 제안하며, 핸들러가 없는 코드 경로를 표시합니다. 하지만 개발자는 배포 전에 논리와 오류 메시지를 여전히 확인해야 합니다.

GitHub 부조종사 의도를 설명하는 간단한 주석을 입력하면 WHEN 절, RAISE_APPLICATION_ERROR 호출 및 전체 EXCEPTION 블록이 자동 완성됩니다. 이를 통해 일상적인 핸들러 코딩 속도가 향상되지만, 생성된 오류 코드와 메시지는 정확성을 위해 검토가 필요합니다.

이 게시물을 요약하면 다음과 같습니다.