1HOON
논리적 코딩
1HOON
전체 방문자
오늘
어제
  • HOME (187)
    • ☕️ JAVA (28)
      • WhiteShip Java LIVE Study (6)
      • Effective JAVA (10)
    • 🔮 KOTLIN (4)
    • 🌱 SPRING (51)
      • 스프링 인 액션 (22)
      • JPA (18)
    • ☕️ JAVASCRIPT (6)
    • 📃 DATABASE (40)
      • ORACLE (37)
      • MSSQL (2)
    • 🐧 LINUX (4)
    • 🐳 DOCKER (5)
    • 🐙 KUBERNETES (4)
    • 🏗️ ARCHITECTURE (8)
    • 📦 ETC (27)
      • TOY PROJECT (5)
      • RECRUIT (1)
      • 그냥 쓰고 싶어서요 (14)
      • TIL (1)
    • 🤿 DEEP DIVE (1)
    • 🚽 Deprecated (9)
      • PYTHON (3)
      • AWS (2)
      • HTTP 완벽가이드 (3)
      • WEB (1)

블로그 메뉴

  • 홈
  • 방명록
  • 관리

인기 글

최근 글

티스토리

hELLO · Designed By 정상우.
1HOON

논리적 코딩

[PL/SQL] 예외처리(2) : 시스템 예외와 사용자정의 예외
📃 DATABASE/ORACLE

[PL/SQL] 예외처리(2) : 시스템 예외와 사용자정의 예외

2018. 1. 25. 17:11

 예외처리(1) : 예외처리란?

 예외처리(2) : 시스템 예외와 사용자 정의 예외

 예외처리(3) : 효율적인 예외처리


시스템 예외

예외처리시 OTHERS 외에 사용할 수 있는 시스템 예외명이 존재하는데, 미리 정의된 예외라고 한다.


종류



예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
CREATE OR REPLACE PROCEDURE EXCEPTION_PROC
IS
    VI_NUM   NUMBER := 0;
BEGIN
    VI_NUM := 10 / 0;
    
    DBMS_OUTPUT.PUT_LINE('SUCCESS');
EXCEPTION
    WHEN ZERO_DIVIDE THEN
         DBMS_OUTPUT.PUT_LINE('오류1');
         DBMS_OUTPUT.PUT_LINE(SQLERRM);
    WHEN OTHERS THEN
         DBMS_OUTPUT.PUT_LINE('오류2');
         DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
 
EXEC EXCEPTION_PROC;
cs



사원번호와 JOB_ID를 매개변수로 받아 해당 사원의 JOB_ID를 갱신하는데, JOB_ID가 JOBS 테이블에 존재하지 않으면 오류 메시지를 출력하고 종료하는 프로시저를 만들어보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
CREATE OR REPLACE PROCEDURE UPD_JOBID_PROC
(   P_EMPLOYEE_ID   EMPLOYEES.EMPLOYEE_ID%TYPE,
    P_JOB_ID        JOBS.JOB_ID%TYPE            )
IS
    VN_CNT  NUMBER := 0;
BEGIN
    SELECT  COUNT(*)
    INTO    VN_CNT
    FROM    JOBS
    WHERE   JOB_ID = P_JOB_ID;
    
    IF  VN_CNT = 0  THEN
        DBMS_OUTPUT.PUT_LINE('JOB_ID가 없습니다.');
    ELSE
        UPDATE  EMPLOYEES
        SET     JOB_ID = P_JOB_ID
        WHERE   EMPLOYEE_ID = P_EMPLOYEE_ID;
    END IF;
    
    COMMIT;
END;
 
EXEC UPD_JOBID_PROC(200, 'SM_JOB2');
cs



IF문이 너무 번거로우므로, IF문 없이 다시 작성해보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
CREATE OR REPLACE PROCEDURE UPD_JOBID_PROC
(   P_EMPLOYEE_ID   EMPLOYEES.EMPLOYEE_ID%TYPE,
    P_JOB_ID        JOBS.JOB_ID%TYPE            )
IS
    VN_CNT  NUMBER := 0;
BEGIN
    SELECT  1
    INTO    VN_CNT
    FROM    JOBS
    WHERE   JOB_ID = P_JOB_ID;
    
    UPDATE  EMPLOYEES
    SET     JOB_ID = P_JOB_ID
    WHERE   EMPLOYEE_ID = P_EMPLOYEE_ID;
    
    COMMIT;
EXCEPTION
    WHEN    NO_DATA_FOUND   THEN
            DBMS_OUTPUT.PUT_LINE(SQLERRM);
            DBMS_OUTPUT.PUT_LINE(P_JOB_ID || '에 해당하는 JOB_ID가 없습니다.');
    WHEN    OTHERS  THEN
            DBMS_OUTPUT.PUT_LINE('기타에러 : ' || SQLERRM);
END;
 
EXEC UPD_JOBID_PROC(200, 'SM_JOB2');
Colored by Color Scripter
cs



예외처리부가 생겨 코드길이는 한 두줄 길어졌지만, 깔끔하기도 하고 의도가 분명한 코드가 된 것 같다.



사용자 정의 예외

사용자가 직접 예외를 정의하고 처리할 로직을 작성한다.


방법

1. 예외 정의

1
사용자정의 예외명 EXCEPTION;
cs

사용자 예외를 사용하려면 일단 변수나 상수처럼 선언부에 예외를 정의해야한다.

2. 예외 발생시키기

1
RAISE 사용자정의 예외명;
cs

시스템 예외는 해당 예외가 자동으로 검출되지만, 사용자 정의 예외는 직접 예외를 발생시켜야한다.

3. 발생된 예외 처리

1
EXCEPTION WHEN 사용자정의 예외명 THEN
cs

예외를 발생시키면 자동으로 제어권이 EXCEPTION으로 넘어오므로 시스템 예외와 동일한 방식으로 처리하면된다.


예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
CREATE OR REPLACE PROCEDURE INS_EMP_PROC
(   P_EMP_NAME      EMPLOYEES.EMP_NAME%TYPE,
    P_DEPARTMENT_ID DEPARTMENTS.DEPARTMENT_ID%TYPE  )
IS
    VN_EMPLOYEE_ID  EMPLOYEES.EMPLOYEE_ID%TYPE;
    VD_CURR_DATE    DATE := SYSDATE;
    VN_CNT          NUMBER := 0;
    
    EX_INVALID_DEPID    EXCEPTION;
BEGIN
    
    SELECT  COUNT(*)
    INTO    VN_CNT
    FROM    DEPARTMENTS
    WHERE   DEPARTMENT_ID = P_DEPARTMENT_ID;
    
    IF  VN_CNT = 0  THEN
        RAISE EX_INVALID_DEPID;
    END IF;
    
    SELECT  MAX(EMPLOYEE_ID) + 1
    INTO    VN_EMPLOYEE_ID
    FROM    EMPLOYEES;
    
    INSERT  INTO    EMPLOYEES (EMPLOYEE_ID, EMP_NAME, HIRE_DATE, DEPARTMENT_ID)
            VALUES  (VN_EMPLOYEE_ID, P_EMP_NAME, VD_CURR_DATE, P_DEPARTMENT_ID);
    
    COMMIT;
EXCEPTION
    WHEN    EX_INVALID_DEPID    THEN
            DBMS_OUTPUT.PUT_LINE('해당 부서 번호가 없습니다.');
    WHEN    OTHERS  THEN
            DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
 
EXEC INS_EMP_PROC('홍길동', 999);
Colored by Color Scripter
cs



원래 부서 테이블에 입력받은 부서ID가 존재하지 않는것은 예외가 아니다. 데이터가 없는게 예외는 아니니깐.

하지만 위 코드에서는 사용자가 입력받은 부서ID가 존재하지 않는것을 예외로 정했기 때문에 예외처리부로 제어권이 넘어온 것이다.



시스템 예외에 이름 부여

예외명이 부여된 시스템 예외는 극소수이기 대문에 나머지는 예외코드로만 존재한다. 하지만 이런 이름없는 예외에 이름을 붙이면 좀 더 편하고 쉽게 사용할 수 있을것이다.


순서

1. 사용자정의 예외 선언

1
사용자정의 예외명 EXCEPTION;
cs

2. 사용자정의 예외명과 시스템 예외코드 연결

1
PRAGMA EXCEPTION_INIT (사용자정의예외명, 시스템예외코드);
cs

3. 발생된 예외 처리


예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
CREATE OR REPLACE PROCEDURE INS_EMP_PROC
(   P_EMP_NAME      EMPLOYEES.EMP_NAME%TYPE,
    P_DEPARTMENT_ID DEPARTMENTS.DEPARTMENT_ID%TYPE,
    P_HIRE_MONTH    VARCHAR2                        )
IS
    VN_EMPLOYEE_ID  EMPLOYEES.EMPLOYEE_ID%TYPE;
    VD_CURR_DATE    DATE := SYSDATE;
    VN_CNT          NUMBER:= 0;
    
    EX_INVALID_DEPID    EXCEPTION;
    EX_INVALID_MONTH    EXCEPTION;
    PRAGMA EXCEPTION_INIT (EX_INVALID_MONTH, -1843);
BEGIN
    SELECT  COUNT(*)
    INTO    VN_CNT
    FROM    DEPARTMENTS
    WHERE   DEPARTMENT_ID = P_DEPARTMENT_ID;
    
    IF  VN_CNT = 0  THEN
        RAISE EX_INVALID_DEPID;
    END IF;
    
    IF  SUBSTR(P_HIRE_MONTH, 5, 2) NOT BETWEEN '01' AND '12' THEN
        RAISE EX_INVALID_MONTH;
    END IF;
    
    SELECT  MAX(EMPLOYEE_ID) + 1
    INTO    VN_EMPLOYEE_ID
    FROM    EMPLOYEES;
    
    INSERT  INTO    EMPLOYEES (EMPLOYEE_ID, EMP_NAME, HIRE_DATE, DEPARTMENT_ID)
            VALUES  (VN_EMPLOYEE_ID, P_EMP_NAME, TO_DATE(P_HIRE_MONTH || '01'), P_DEPARTMENT_ID);
            
    COMMIT;
EXCEPTION
    WHEN    EX_INVALID_DEPID    THEN
            DBMS_OUTPUT.PUT_LINE('해당 부서번호가 없습니다');
    WHEN    EX_INVALID_MONTH    THEN
            DBMS_OUTPUT.PUT_LINE(SQLCODE);
            DBMS_OUTPUT.PUT_LINE(SQLERRM);
            DBMS_OUTPUT.PUT_LINE('1~12월 범위를 벗어났습니다');
    WHEN    OTHERS  THEN
            DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
 
EXEC INS_EMP_PROC('홍길동', 110, '201314');
Colored by Color Scripter
cs



주의할 점

미리 정의된 예외 중 NO_DATA_FOUND(-1403)은 사용자 정의 예외명에 해당 코드를 연결할 수 없다. 만약 연결할 경우 컴파일시 다움과 같은 오류가 발생한다.

예) PRAGMA EXCEPTION_INIT에 대한 부당한 ORACLE 오류번호(-1403)입니다.

 예외 코드로 0이나 100을 제외한 양수, 그리고 -10000000 이하 값은 사용할 수 없다.

 동일한 예외명으로 다른 예외 코드를 2개이상 연결하면, 맨 마지막에 연결한 코드가 적용된다.



RAISE와 RAISE_APPLICATION_ERROR

사용자 정의 예외명을 선언하고 미리 정의된 예외코드를 연결하거나 사용자 정의 예외를 선언하지않고 바로 미리 정의된 예외를 발생시킬 수 있다.


예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
CREATE OR REPLACE PROCEDURE RAISE_TEST_PROC
(   P_NUM   NUMBER  )
IS
BEGIN
    IF  P_NUM <= 0  THEN
        RAISE INVALID_NUMBER;
    END IF;
    
    DBMS_OUTPUT.PUT_LINE(P_NUM);
EXCEPTION
    WHEN    INVALID_NUMBER  THEN
            DBMS_OUTPUT.PUT_LINE('양수만 입력받을 수 있습니다.');
    WHEN    OTHERS  THEN
            DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
 
EXEC RAISE_TEST_PROC(-10);
cs



RAISE_APPLICATION_ERROR

시스템 패키지에 속한 프로시저이다. 사용자 정의 예외만 발생시킬 수 있고, 원하는 예외 코드와 메시지를 직접 매개변수로 받는다.

1
RAISE_APPLICATION_ERROR(예외코드, 예외메시지);
cs


예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CREATE OR REPLACE PROCEDURE RAISE_TEST_PROC
(   P_NUM   NUMBER  )
IS
BEGIN
    IF  P_NUM <= 0  THEN
        RAISE_APPLICATION_ERROR(-20000, '양수만 입력받을 수 있습니다.');
    END IF;
    
    DBMS_OUTPUT.PUT_LINE(P_NUM);
EXCEPTION
    WHEN    INVALID_NUMBER  THEN
            DBMS_OUTPUT.PUT_LINE('양수만 입력받을 수 있습니다.');
    WHEN    OTHERS  THEN
            DBMS_OUTPUT.PUT_LINE(SQLCODE);
            DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
 
EXEC RAISE_TEST_PROC(-10);
Colored by Color Scripter
cs




 예외처리(1) : 예외처리란?

 예외처리(2) : 시스템 예외와 사용자 정의 예외

 예외처리(3) : 효율적인 예외처리

반응형
저작자표시 비영리 변경금지 (새창열림)

'📃 DATABASE > ORACLE' 카테고리의 다른 글

[PL/SQL] 트랜잭션  (1) 2018.01.29
[PL/SQL] 예외처리(3) : 효율적인 예외처리  (2) 2018.01.26
[PL/SQL] 예외처리 (1) : 예외처리란?  (0) 2018.01.24
[PL/SQL] 프로시저(PROCEDURE)  (0) 2018.01.23
[PL/SQL] 사용자 정의함수  (0) 2018.01.22
    '📃 DATABASE/ORACLE' 카테고리의 다른 글
    • [PL/SQL] 트랜잭션
    • [PL/SQL] 예외처리(3) : 효율적인 예외처리
    • [PL/SQL] 예외처리 (1) : 예외처리란?
    • [PL/SQL] 프로시저(PROCEDURE)
    1HOON
    1HOON

    티스토리툴바