예외처리의 기초
예시를 먼저 보도록 하자.
시작하기 앞서, 테이블에 제약조건을 추가하자.
1 2 | ALTER TABLE emp ADD CONSTRAINT emp_ck CHECK ( sal > 0 ) ; | cs |
제약조건 때문에 다음의 구문은 ERROR가 발생한다.
1 2 3 | UPDATE emp SET sal = 0 WHERE empno = 7934 ; | cs |
다음의 PL/SQL 블록은 비정상 종료가 이뤄진다.
1 2 3 4 5 6 7 8 9 10 11 | BEGIN UPDATE emp SET sal = 3000 WHERE empno = 7782 ; UPDATE emp SET sal = 0 WHERE empno = 7934 ; END ; / --블록 내에서 ERROR 발생시 블록 전체가 ROLLBACK된다.(비정상 종료) | cs |
하지만 다음과 같이 예외처리를 해주면
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | BEGIN UPDATE emp SET sal = 3000 WHERE empno = 7782 ; UPDATE emp SET sal = 0 WHERE empno = 7934 ; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE ( SQLERRM ) ; END ; / | cs |
PL/SQL의 블록에서 에러가 발생한 지점에서 EXCEPTION절로 넘어가고 예외처리기를 통해 순차적으로 진행을 하고, 다시 돌아가지 않고, END로 빠져나간다.
그러면 예외를 알아보도록 하자.
예외란
블록 실행 중 에 발생한 PL/SQL 오류를 말한다.
예외는 세가지 유형으로 분류된다.
>암시적 예외
- 미리 정의된 Oracle 서버 오류
- 미리 정의되지 않은 Oracle 서버오류
>명시적 예외
- 유저 정의 오류
예외 트랩 구문은 다음과 같다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | EXCEPTION WHEN exception1 [OR exception2...] THEN statement1; statement2; ... [WHEN exception3 [OR exception4...] THEN statement1; statement2; ...] [WHEN OTHERS THEN statement1; statement2; ...] | cs |
구문 |
설명 |
exception |
예외의 이름 |
statement |
하나 이상의 PL/SQL 또는 SQL문 |
OTHERS |
명시적 처리되지않은 예외를 전부 선택 |
미리 정의되지 않은 오류 트랩의 경우
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | DECLARE emp_rec emp%ROWTYPE ; e_ck EXCEPTION ; PRAGMA EXCEPTION_INIT (e_ck , -2290) ; BEGIN SELECT * INTO emp_rec FROM emp WHERE ename = UPPER('&name') ; IF emp_rec.sal < 2000 THEN UPDATE emp SET sal = &salary WHERE empno = emp_rec.empno ; END IF ; EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE ('NO DATA') ; WHEN E_CK THEN DBMS_OUTPUT.PUT_LINE ('Invalid Salary') ; WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE (SQLERRM) ; END ; / | cs |
다음과 같이 선언부에 예외 이름과, Oracle 서버 오류 코드를 트랩해야 한다.
예외 트랩에 대한 함수
함수 |
설명 |
SQLCODE |
오류코드에 대한 숫자 값 반환 |
SQLERRM |
오류번호와 연관된 메시지를 포함하는 문자 데이터를 반환 |
주의할 점으로는 EXCEPTION절이 없으면 비정상 종료이다.
유저 정의 예외 트랩
RAISE_APPLICATION_ERROR 프로시저
다음과 같은 구문을 사용한다.
1 2 | raise_application_error (error_number, message[, {TRUE | FALSE}]); | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | BEGIN UPDATE emp SET sal = 3000 WHERE empno = 7782 ; UPDATE dept SET dname = 'Testing' WHERE deptno = 50 ; IF SQL%NOTFOUND THEN RAISE_APPLICATION_ERROR ( -20001, 'No such department id.' ) ; END IF; UPDATE emp SET sal = 3000 WHERE empno = 7566 ; END; / | cs |
즉 위의 예시는 비정상 종료이고,
다음 예시는 에러가 나기 전까지 실행되고 정상종료된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | BEGIN UPDATE emp SET sal = 3000 WHERE empno = 7782 ; UPDATE dept SET dname = 'Testing' WHERE deptno = 50 ; IF SQL%NOTFOUND THEN RAISE_APPLICATION_ERROR ( -20001, 'No such department id.' ) ; END IF; UPDATE emp SET sal = 3000 WHERE empno = 7566 ; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(SQLERRM) ; END; / | cs |
다음 서브 블록의 경우 비정상 종료가 된다.
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 | BEGIN UPDATE emp SET sal = 7777 WHERE empno = 7788 ; BEGIN UPDATE emp SET sal = 9999 WHERE empno = 7566 ; UPDATE emp SET sal = 0 WHERE empno = 7839 ; UPDATE emp SET sal = 9999 WHERE empno = 7499 ; END ; UPDATE emp SET sal = 7777 WHERE empno = 7369 ; END ; / | 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 | BEGIN UPDATE emp SET sal = 7777 WHERE empno = 7788 ; BEGIN UPDATE emp SET sal = 9999 WHERE empno = 7566 ; UPDATE emp SET sal = 0 WHERE empno = 7839 ; UPDATE emp SET sal = 9999 WHERE empno = 7499 ; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE (SQLERRM) ; END ; UPDATE emp SET sal = 7777 WHERE empno = 7369 ; END ; / | cs |
중첩된 블록은 정상 종료되고, 밖의 블록이 정상적으로 진행된다.
그다음 중첩된 블록 밖에서 EXCETPION절이 있는 경우
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 | BEGIN UPDATE emp SET sal = 7777 WHERE empno = 7788 ; BEGIN UPDATE emp SET sal = 9999 WHERE empno = 7566 ; UPDATE emp SET sal = 0 WHERE empno = 7839 ; UPDATE emp SET sal = 9999 WHERE empno = 7499 ; END ; UPDATE emp SET sal = 7777 WHERE empno = 7369 ; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE (SQLERRM) ; END ; / | cs |
이경우에는 첫번쨰 UPDATE만 살리고 나머지는 전부 종료된다.
SQL을 배운지 얼마 되지 않아 잘못된 내용이 있을 수 있습니다. 틀린 내용이있다면, 댓글로 달아주세요.
'DATABASE(oracleDB 11g) > PLSQL' 카테고리의 다른 글
[PL/SQL]동적 SQL의 기초 (0) | 2019.02.22 |
---|---|
[PL/SQL]패키지 작업의 기초 (0) | 2019.02.22 |
[PL/SQL]명시적 커서 기초 (0) | 2019.02.19 |
[PL/SQL]조합 데이터 유형 작업 기초 (0) | 2019.02.19 |
[PL/SQL]제어구조문의 기초 (0) | 2019.02.19 |