에러 처리
tbPSM 프로그램에서 발생하는 에러를 처리하는 방법을 설명합니다.
개요
에러는 tbPSM 프로그램에서 다음과 같은 경우에 발생할 수 있습니다.
컴파일 중일 때 컴파일 중에 발생하는 에러는 tbPSM이 발견하여 사용자에게 보고합니다. 이 경우 프로그램은 아직 실행 되지 않은 상태이며, 사용자에 의해 수정되어야 합니다.
프로그램이 실행 중일 때 에러를 처리하기 위해서는 예외 상황과 예외 처리 루틴을 사용합니다. 에러가 발생하면 프로그램은 비정상적으로 종료되며, 사용자는 원하는 결과를 얻을 수 없습니다. 따라서 에러 발생이 예상되는 부분을 예외 상황으로 정의하고 예외 처리 루틴을 만듭니다. 그러면 프로그램을 작성하거나 디버깅할 때 편리하게 작업할 수 있습니다. 다음은 프로그램이 실행 중일 때 발생한 에러를 처리하는 예입니다.
DECLARE
a NUMBER := 5;
b NUMBER := 0;
BEGIN
a := a / b;
END;위의 프로그램을 실행하면 다음과 같은 에러가 발생하고 프로그램은 비정상적으로 종료됩니다.
TBR-5070: Divide by zero error.
TBR-15163: Unhandled exception at line 5.에러가 발생하면 다음과 같이 예외 처리 루틴을 만듭니다.
DECLARE
a NUMBER := 5;
b NUMBER := 0;
BEGIN
a := a / b;
EXCEPTION
WHEN OTHERS THEN
handle_numeric_error(b);
END;위 예에서 보듯이 에러가 발생하면 예외 처리 루틴으로 제어가 이동되고 handle_numeric_error 함수가 호출됩니다. 이 프로그램은 예외 처리 루틴에 의해 자동으로 에러가 처리되며, 정상적으로 종료됩니다.
예외 상황 선언
발생된 에러를 예외 상황으로 정의하기 위해서는 우선 먼저 예외 상황을 선언해야 합니다. 선언하는 방법은
tbPSM의 변수의 선언과 같습니다.
시스템 정의 예외
tbPSM 프로그램에서 발생하기 쉬운 에러를 시스템에 미리 정의하는 것을 시스템 정의 예외라고 합니다.
시스템 정의 예외는 사용자가 프로그램의 선언부에 예외 상황을 명시적으로 선언하지 않아도 사용할 수 있습니다. 또한 에러와 예외 상황이 자동으로 연결되어 있어 사용자가 명시적으로 연결하지 않아도 에러가 발 생하면 자동적으로 예외 상황이 됩니다.
시스템 정의 예외를 선언하는 방법은 다음과 같습니다.
시스템 정의 예외는 다음과 같은 예외 상황이 존재합니다.
CASE_NOT_FOUND
CASE 문의 WHEN 절 중에서 조건을 만족하는 것이 없고 ELSE 절 도 없는 경우
CURSOR_ALREADY_OPEN
이미 열려 있는 커서를 또 다시 여는 경우
DUP_VAL_ON_INDEX
유일 키(UNIQUE) 제약조건이 선언되어 있는 컬럼에 중복된 값을 삽 입하려는 경우
INVALID_CURSOR
열려 있지 않은 커서를 닫는 경우
NO_DATA_FOUND
SELECT INTO에 의한 질의에서 결과 로우가 하나도 없는 경우
TOO_MANY_ROWS
SELECT INTO에 의한 질의에서 결과 로우가 둘 이상인 경우
VALUE_ERROR
데이터 값의 변환(conversion), 절단(truncation), 제약조건 등과 관련 된 에러가 발생한 경우
ZERO_DIVIDE
0으로 나눗셈 연산을 수행하는 경우
COLLECTION_IS_NULL
초기화되지 않은 컬렉션 변수의 요소에 값을 대입하려는 경우
초기화되지 않은 컬렉션 변수에 EXISTS를 제외한 서브 프로그램을 사용하는 경우
SUBSCRIPT_BEYOND_COUNT
컬렉션 변수에 있는 요소의 개수보다 큰 인덱스를 사용하는 경우
SUBSCRIPT_OUTSIDE_LIMIT
컬렉션 변수를 접근하는 인덱스가 유효하지 않은 경우(예: -1)
ROWTYPE_MISMATCH
커서 변수의 타입과 PSM 내부에서 사용한 커서 변수의 타입이 맞지 않은 경우
INVALID_NUMBER
주어진 문자열이 number로 적절한 문자열 형태가 아닌 경우
다음은 시스템 정의 예외의 예입니다.
본 예에서는 employee_grade 변수에 'S'라는 값을 할당하였으며, CASE 문에서 'S'를 찾지 못하면 이 프로그램은 에러를 발생하게 됩니다. tbPSM은 이러한 에러를 처리하기 위해 case_not_found라는 시스템 정의 예외를 정의하였으며, 사용자는 예외 상황을 선언하는 과정 없이 바로 사용할 수 있습니다. 또한 에러 처리 루 틴도 정의할 수 있습니다. 만약 이 예에서 에러가 발생합니다면 사용자가 정의한 예외 처리 루틴으로 이동하게 되고, 프로그램은 정상적으로 종료됩니다.
사용자 정의 예외
시스템 정의 예외 이외에 프로그램을 실행하는 중에 발생할 가능성이 있는 예외 상황을 사용자 정의 예외로 선언할 수 있습니다. 이러한 예외 상황은 일반적인 변수와 같이 프로그램의 선언부에 선언할 수 있습니다. 사용자 정의 예외를 선언하는 방법은 다음과 같습니다.
exception name은 사용자가 원하는 이름으로 선언할 수 있습니다. 선언된 예외 상황은 일반적인 변수처럼 영역을 갖게 됩니다. 예외 상황의 영역은 선언된 블록의 끝까지 입니다.
사용자 정의 예외를 사용하는 방법에는 다음과 같이 두 가지가 있습니다.
RAISE 문 사용 시스템 정의 예외와는 다르게 사용자 정의 예외는 에러와 예외 상황을 연결하기 위해서는 RAISE 문을 사용해야 합니다. RAISE 문에서 사용자 정의 예외를 사용하는 문법은 다음과 같습니다.
사용자는 원하는 위치에 RAISE 문을 사용하여 예외 상황을 발생시킬 수 있습니다. 만약 예외 상황이 발생되 면 제어는 예외 처리 루틴으로 이동하게 된다. 다음은 RAISE 문의 예입니다.
RAISE_APPLICATION_ERROR 프러시저 사용 RAISE_APPLICATION_ERROR 프러시저에서 사용자 정의 예외를 사용하는 문법은 다음과 같습니다.
error_number
-20000 ~ -20999 사이의 값만 사용할 수 있음
error_message
에러 메시지의 길이는 712bytes까지 가능
712bytes를 초과하는 메시지는 712bytes까지만 사용
{true|false}
true: 기존에 존재하는 에러에 추가
false: 기존에 존재하는 에러를 모두 삭제
다음은 RAISE_APPLICATION_ERROR 프러시저의 예입니다.
예외 처리 루틴
예외 처리 루틴은 다음과 같은 절차로 실행됩니다.
예외 상황이 발생하면 예외 처리 루틴으로 이동합니다.
예외 처리 루틴이 실행됩니다.
실행이 끝나면, 외부 블록으로 이동합니다.
외부 블록을 실행합니다. 만약 외부 블록이 없으면 해당 프로그램은 종료됩니다.
프로그램을 종료합니다.
예외 처리 루틴 형식
시스템 정의 예외나 사용자 정의 예외와 관계없이 예외 처리 루틴은 동일한 형식으로 사용됩니다. 예외 처리 루틴은 선언부, 실행부와 같이 tbPSM 프로그램 내부의 블록의 한 종류로 표현됩니다.
예외 처리 루틴의 형식은 다음과 같은 특징을 가집니다.
EXCEPTION으로 시작하고 해당 블록이 끝나는 END 사이에 정의됩니다.
EXCEPTION의 바로 앞에서 프로그램의 실행부는 끝납니다.
예외 처리 루틴 내부에 WHEN 문을 사용합니다. 해당 블록에서 발생할 가능성이 있는 예외 상황을 구분하여 처리할 각 실행문(또는 실행문의 집합)을 설정합니다. 또한 WHEN 문에서 서로 다른 예외 상황들은 OR로 묶어서 처리할 수 있습니다.
WHEN 문에 정의된 실행문은 앞에서부터 순차적으로 실행됩니다. 만약 발생된 예외 상황에 실행문이 예외 처리 루틴 안에 정의되어 있지 않으면 새로운 예외 상황이 발생하게 됩니다.
정의되지 않은 예외 상황을 처리하려면 OTHERS 문을 사용합니다.
OTHERS 문은 이전에 명시된 예외 상황을 제외한 모든 예외 상황을 처리하기 때문에 예외 처리 루틴의 맨 마지막에 사용합니다. OTHERS 문 이후에 또 다른 예외 처리 핸들러가 오는 경우 새로운 예외 상황이 발생합니다.
OTHERS 문을 사용하는 문법은 다음과 같습니다.
예외 상황 전파
예외 상황은 tbPSM 프로그램의 모든 부분 즉 tbPSM 블록의 선언부, 실행부, 예외 처리 루틴에서 발생할 수 있습니다. 대체로 tbPSM의 블록의 선언부나 예외 처리 루틴에서 예외 상황이 발생하는 경우 또는 발생한 예외 상황에 대해 예외 처리 루틴이 없는 경우 등이 빈번하게 발생합니다. 이와 같은 경우를 통제하기 위한 과정을 예외 상황의 전파(Exception Propagation)라 합니다.
본 절에서는 이러한 예외 상황의 전파에 대해 케이스 별로 예를 들어 다음과 같이 설명합니다.
선언부에서 예외 상황이 발생한 경우
다음은 선언부에서 예외 상황이 발생한 예입니다.
선언부에서 예외 상황이 발생한 경우 발생 즉시 외부 블록으로 전파됩니다. 예외 상황이 발생한 블록에 예외 처리 루틴이 있어도 이 처리 루틴은 무시됩니다.
OTHERS 문을 이용한 예외 상황 처리
다음은 외부 블록의 예외 처리 루틴 중에서 OTHERS 문에 의해 내부 블록의 VALUE_ERROR가 처리되는 경우의 예입니다. 이때 프로그램은 정상적으로 종료됩니다.
RAISE 문을 이용한 예외 상황 처리
예외 처리 루틴 내에서도 사용자의 필요에 의해 RAISE 문을 사용하여 명시적으로 예외를 발생시키거나, 사용자가 의도하지 않은 런타임 에러가 발생할 수 있습니다. 이렇게 발생된 예외 상황은 선언부에서와 같이 외부 블록으로 바로 전파된다.
다음은 RAISE 문을 이용하여 예외 상황을 처리하는 예입니다.
예외 상황은 위 예에서처럼 한 번에 하나씩 발생됩니다. 물론 이렇게 발생된 하나의 예외 상황이 처리되자 마자 또 다른 예외 상황이 발생될 수 있지만, 동시에 두 개 이상의 예외 상황이 발생될 수는 없습니다.
다음은 RAISE 문에 예외 상황을 명시하지 않아, 예외 상황을 처리할 때 불필요한 실행이 발생하지 않도록 작성한 프로그램의 예입니다.
예외 처리 루틴의 존재 여부
실행부에서 예외가 발생하였으나 예외 처리 루틴이 없는 경우 또는 예외 처리 루틴은 있지만 발생된 예외 상황을 처리할 수 없는 경우에 예외 상황은 외부 블록으로 전파됩니다.
위의 예에서는 내부 블록에서 발생한 예외 상황 a를 처리할 수 있는 예외 처리 루틴이 존재합니다. 따라서 정상적으로 내부 블록을 실행하고 제어를 다시 외부 블록으로 넘김으로써 나머지 부분을 계속 수행하게 됩니다.
반면에 다음의 예는 다릅니다.
이 예에서는 내부 블록에 예외 상황 b를 처리하기 위한 예외 처리 루틴이 없으므로 예외 상황은 외부 블록으로 전파됩니다. 이렇게 전파된 예외 상황은 외부 블록에서 정상적으로 종료됩니다.
추가로 외부 블록에서도 발생한 예외 상황을 처리하기 위한 에러 처리 루틴이 없을 수 있습니다. 이러한 경우 예외 상황은 다시 상위 블록으로 계속 전파됩니다. 이때 상위 블록의 작업이 끝나면 예외 상황은 처리되지 못하고 프로그램은 비정상적으로 종료됩니다.
에러 정보
에러에 대한 정보를 얻기 위해서는 Tibero가 제공하는 함수 중에 SQLCODE와 SQLERRM를 사용해야 합니다. SQLCODE 함수는 에러 코드를 반환하고, SQLERRM 함수는 에러 메시지를 반환합니다. 이 두 함수는 SQL 문장 내에서 직접 사용할 수 없으며, 변수에 할당하여 사용합니다.
다음은 SQLCODE와 SQLERRM 함수를 통해 얻을 수 있는 결과입니다.
에러가 발생하지 않은 경우
0
normal, successful completion
사용자 정의 에러
1
user-defined exception
NO_DATA_FOUND
100
no data found
기타 예외 상황
해당 에러 코드
해당 에러 메시지
SQLERRM을 parameter없이 사용하면 에러 스택의 탑에 있는 에러의 메시지를 반환하고, SQLERRM(SQL CODE)의 경우 에러 스택과는 관계없이 SQL 코드에 해당하는 에러의 메시지를 반환합니다.
다음은 SQLCODE와 SQLERRM 함수의 예입니다.
Last updated

