예외처리
PL/SQL 코드를 작성할 때 발생할 수 있는 오류에는 크게 두 가지가 있다. 하나는 문법 오류로써 객체(테이블, 뷰, 함수, 프로시저 등)나 키워드 이름을 잘못 참조하거나 함수나 프로시저의 매개변수를 잘못 명시했을 때 발생되는 오류로 이들은 컴파일할 때 걸러진다. 두 번째는 컴파일 때는 아무런 문제가 없으나 런타임 때 로직을 처리하면서 발생하는 오류인데 이를 예외exception 라고 한다. 컴파일 시 발생하는 오류도 예외에 속하긴 하지만 보통 예외라고 하면 런타임 때의 오류를 말한다.
예외에는 다시 오라클에서 발생시키는 시스템 예외와 사용자가 의도적으로 발생시킬 수 있는 사용자 정의 예외로 구분할 수 있다. 시스템 예외로는 나눗셈 연산을 할 때 0으로 나눈다거나 SELECT INTO 절을 사용해 데이터를 가져올 때 조건에 만족하는 데이터가 없으면 발생하는 예외 등이 있다. 시스템 예외는 오라클 내부에 미리 정의된 예외라고 할 수 있다. 이에 반해 사용자 정의 예외는 사용자가 직접 예외를 정의해서 사용하는 것을 말한다. 먼저 예외처리 구문에 대해 살펴 보자.
기본구문
예외처리 구문을 보면 CASE문과 비슷한 구조임을 알 수 있다. 처리할 예외명을 언급하고 그 예외에 해당되면 예외처리 구문을 나열하는 식이다. WHEN 다음에 위치하는 예외명은 아무 이름이나 사용할 수는 없고 시스템 예외 중 일부와 사용자가 직접 정의한 예외명을 사용할 수 있다. 구체적인 예외명을 알 수 없을 때는 OTHERS를 사용하면 되는데 이렇게 하면 오라클 시스템에서 PL/SQL 코드 상에서 발생한 런타임 예외를 자동으로 잡아 준다. 자동으로 예외를 잡아 주니 이때 처리할 수 있는 예외는 물론 시스템 예외에 한정된다. 그러면 의도적으로 예외를 발생시켜 보자.
◈ 예제
10을 0으로 나누려니 오류가 발생했다. 예외처리 구문을 사용하지 않으니 시스템에서 오류를 뱉어낸 것이다. 이번에는 예외처리 구문을 넣어 보자.
예외처리 구문 덕분에 시스템 에러 대신 “오류가 발생했습니다”란 메시지가 출력되었다. PL/SQL 코드의 실행부에서 예외가 발생하는 즉시 이후 코드는 처리되지 않고 제어권은 예외처리 구문으로 넘어간다. 먼저 위의 익명 블록을 예외처리 부분이 있는 것과 없는 것으로 나누어 2개의 프로시저로 만들어 보자.
◈ 예제
<예외처리 없는 프로시저>
<예외처리 있는 프로시저>
예외처리가 없는 프로시저를 실행했더니 시스템에서 예외를 발생시켜 해당 프로시저 실행이 중단됐음은 물론 익명 블록에서 “Success!”를 출력하는 부분도 실행되지 않았다. 반면 예외처리가 구현된 프로시저를 실행했을 때는 예외 처리부로 제어권이 넘어가 “오류가 발생했습니다”란 메시지를 출력한 다음 익명 블록의 “Success!”란 메시지도 출력되었다.
예외처리를 함으로써 개발자가 프로그램 제어권을 획득해 여러 단계에 걸쳐 수행되는 프로그램의 정상적 동작을 보장할 수 있었는데 반해 예외처리를 하지 않으면 오류가 난 시점에 프로그램의 흐름이 끊어져 버린다. 따라서 아주 간단한 코드를 작성할 때 조차도 반드시 예외처리 구문을 넣도록 하자.
시스템 예외
예외처리 시 OTHERS 외에도 시스템 예외명을 사용할 수 있는데 이를 미리 정의된 예외predefined exception라 한다. 즉 고유의 예외명칭을 사용할 수 있다는 것인데 이들 중 대표적인 예외를 정리하면 다음과 같다.
위의 표를 보면 젯수가 0일 때의 예외가 ‘ZERO_DIVIDE’이므로, 예외처리 구문에서 OTHERS 대신 사용할 수 있다.
◈ 예제
미리 정의된 예외는 그 수가 제한되어 있지만 오라클 내부에서 처리하는 예외의 수는 매우 많다. 따라서 보통 예외처리를 할 때 미리 정의된 예외를 먼저쓰고 맨 마지막에 OTHERS를 명시하는 형태로 사용한다. 여러 개의 예외를 명시할 때 OTHERS는 반드시 맨 끝에 명시해야 한다. 이제 2개 이상의 예외명을 명시해 보자.
결과를 보면 알겠지만 예외처리는 EXCEPTION 절에 명시한 순서대로 처리된다. 맨 처음 명시한 예외가 발생하면 해당되는 로직을 처리하고 이후 예외는 무시하고 프로시저는 종료된다.
'SQL' 카테고리의 다른 글
[SQL 24] 프로시저 생성, 실행 (0) | 2020.06.11 |
---|---|
[SQL 23] PL/SQL 제어문 (FOR 문, CONTINUE문, NULL문) (0) | 2020.06.10 |
[SQL 22] PL/SQL 제어문 (IF 문, CASE 문, LOOP 문, WHILE 문) (0) | 2020.06.10 |
[SQL 21] PL/SQL 구성요소 (0) | 2020.06.09 |
[SQL 20] 서브쿼리 , 인라인뷰 (0) | 2020.06.09 |