2020/01/13 - [DATABASE/ORACLE] - [PL/SQL] 무작정 시작하기 (1) - PL/SQL 이란?
2020/01/13 - [DATABASE/ORACLE] - [PL/SQL] 무작정 시작하기 (2) - IF 조건문
2020/01/13 - [DATABASE/ORACLE] - [PL/SQL] 무작성 시작하기 (3) - LOOP, WHILE 반복문
2020/01/14 - [DATABASE/ORACLE] - [PL/SQL] 무작정 시작하기 (4) - CURSOR
지난 포스트에서는 PL/SQL에서 가장 많이 사용되는 CURSOR에 대해서 다루어 보았다. CURSOR와 더불어 PL/SQL에서 가장 중요한 요소라고 생각하는 것은 바로 예외(Exception)처리이다. 왜냐하면, 대부분의 프로그램에서 예외가 발생하는 경우 중 가장 많은 비율을 차지하는 것이 바로 '예상되지 않은 데이터'가 유입된다는 것인데, 데이터를 직접적으로 조작하는 PL/SQL에서는 당연히 필수적인 요소라고 생각하기 때문이다. 그래서 이번 포스트에서는 예외처리(Exception)에 대해서 다루어보려고 한다.
1. 예외(Exception)처리란?
1-1. 프로그램이 수행하던 중 예상하지 못한 오류가 발생했을 때의 대처 방안.
1-2. 오류가 발생했을 때, 오류 종류에 따라 제어할 수 있음.
- 크리컬한 오류인 경우 프로그램을 종료.
- 시스템의 영향도가 작은 오류라면 무시하고 계속 진행.
1-3. PL/SQL에서는 주로 로그를 남기거나 TCL(트렌젝션 제어어, COMMIT, ROLLBACK )을 처리함.
1-4. 사용자 임의의 EXCEPTION을 정의할 수 있음.
- 단, 사용자 정의 EXCEPTION은 SQLCODE는 '1', SQLERRM은 'User-Defined Exception'으로 출력됨.
- 따라서, 메시지가 필요한 경우 별도의 과정이 필요함.
1-5. 단, 순수 SQL로 작성된 쿼리에서 발생한 오류는 PL/SQL에서 EXCEPTION으로 캐치할 수 없음.
2. 기본 구조.
2-1. BEGIN과 END 사이에 위치하며, CASE WHEN문과 같이 분기처리할 수 있음.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
DECLARE
BEGIN
EXCEPTION
WHEN SOME_EXCEPTION THEN
COMMIT;
WHEN OTHERS THEN
V_RESULT_MSG := 'SQLCODE['||SQLCODE||'], MESSAGE =>'||SQLERRM;
DBMS_OUTPUT.PUT_LINE( V_RESULT_MSG );
ROLLBACK;
END;
|
cs |
- 6 ln: SOME_EXCEPTION은 사용자가 정의한 EXCEPTION을 의미함.
- 7 ln: EXCEPTION이 발생했을 경우 COMMIT을 하도록 함.
- 10 ln: 여기서 OTHERS는 상위 조건을 제외한 모든 EXCEPTION을 의미함.
- 11~15 ln: SQLCODE, SQLERRM과 같이 내장 변수를 사용하여 로그를 출력할 수 있음.
3. 사용예제.
3-1. 부서번호가 '30'인 사원에게 연봉의 10%를 보너스로 지급한다. 단, 대상이 10명 미만인 경우 취소하시오.
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
47
48
|
DECLARE
V_INSERTCNT NUMBER;
MY_EXCEPTION EXCEPTION;
BEGIN
BEGIN
/* 순수 SQL로 작성된 QUERY */
INSERT INTO SCOTT.BONUS T1 ( ENAME, JOB, SAL, COMM )
SELECT T2.ENAME
, T2.JOB
, T2.SAL+(T2.SAL*0.1) AS SAL
, T2.COMM
FROM SCOTT.EMP T2
WHERE 1=1
AND T2.DEPTNO = 30
;
V_INSERTCNT := SQL%ROWCOUNT;
IF V_INSERTCNT < 10 THEN
RAISE MY_EXCEPTION;
END IF;
COMMIT;
DBMS_OUTPUT.PUT_LINE( 'COMMIT -> '||V_INSERTCNT );
EXCEPTION
WHEN MY_EXCEPTION THEN
ROLLBACK;
DBMS_OUTPUT.PUT_LINE( 'ROLLBACK -> '||V_INSERTCNT );
DBMS_OUTPUT.PUT_LINE( 'MY_EXCEPTION -> '||SQLERRM );
RAISE_APPLICATION_ERROR(-20001, '보너스 지급 대상이 10명 미만입니다.');
WHEN OTHERS THEN
ROLLBACK;
DBMS_OUTPUT.PUT_LINE( 'ROLLBACK -> '||V_INSERTCNT );
DBMS_OUTPUT.PUT_LINE( 'INTERNAL OTHERS EXCEPTION -> '||SQLERRM );
END;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE( 'EXTERNAL OTHERS EXCEPTION -> '||SQLERRM );
END;
|
cs |
- 4 ln: 사용자 정의 Exception생성.
- 20 ln: SQL%ROWCOUNT에는 가장 최근 처리된 SQL의 처리행의 수가 담겨있음.
*SQL% 변수는 COMMIT, ROLLBACK이 되면 초기화됨.
- 23 ln: 사용자 정의 Exception호출.
- 31~35 ln: 사용자 정의 Exception을 캐치하여 정해진 로직을 수행.
*SQLCODE와 SQLERRM은 내장 변수
- 35 ln: 사용자 정의 Exception에 코드와 메시지를 정의해주기위해 RAISE_APPLICATION_ERROR 함수 사용.
- 37~40 ln: 나머지 모든 Exception을 캐치하여 정해진 로직을 수행.
- 44~46 ln: 내부 Block에서 발생한 Exception을 캐치.
3-2. RAISE_APPLICATION_ERROR 함수
- 사용자 에러코드 및 에러메시지를 정의하고 Exception을 발생시키는 함수.
- 이 방법은 현재 블록에서 Exception을 발생시켜 상위로 전파하므로 상위에서 Exception을 한번 더 캐치해야함.
문법) RAISE_APPLICATION_ERROR( *SQLCODE, SQLERRM );
사용) RAISE_APPLICATION_ERROR( -20001, '사용자 오류가 발생하였습니다.');
*SQLCODE는 -20000에서 -29999 사이의 값으로 지정.
4. 마치며.
- 3번 예제에 Exception을 다루는 방법을 최대한 많이 녹여내었다. 사실 저정도만 사용해도 크게 문제 없이 사용할 수 있다고 생각한다.
'DATABASE > ORACLE' 카테고리의 다른 글
[SQL] WITH문 (2) | 2020.01.22 |
---|---|
[PL/SQL] 예제 (1) - 1~100의 수를 더하는 과정을 출력 (0) | 2020.01.22 |
[PL/SQL] 무작정 시작하기 (4) - CURSOR (0) | 2020.01.14 |
[PL/SQL] 무작성 시작하기 (3) - LOOP, WHILE 반복문 (0) | 2020.01.13 |
[PL/SQL] 무작정 시작하기 (2) - IF 조건문 (0) | 2020.01.13 |
댓글