💡예외 처리
예외 처리는 실행부에서(being~end) 발생하는 예외를 처리하는 블록(exception 블록)이다.
예외 발생
--ORA-06502: PL/SQL: numeric or value error: character string buffer too small
DECLARE
vname varchar2(5);
BEGIN
dbms_output.put_line('하나');
SELECT name INTO vname FROM tblInsa WHERE num = 1001;
dbms_output.put_line('둘');
dbms_output.put_line(vname);
END;
위 프로시저는 변수의 길이가 저장하려는 데이터보다 짧아 오류가 발생하고 있다.
절차를 갖게 되었을 때의 에러 발생은 실행 자체에 에러가 있는 게 아니다. 기능이 잘 동작할 때까지는 업무가 진행이 되는 걸 볼 수 있는데, 이는 전형적인 흐름이 있는 프로그래밍 언어(절차지향 언어)에서 볼 수 있는 특징이다.
이와 같이 오류가 발생하면 올바른 종료가 이루어진 게 아니라 작업 도중에 올스톱 된 것이기 때문에 안정성에 문제가 있다.
에러는 늘 있을 수 있다. 때문에 해결하는 대신에 예외처리 코드를 실행해서 에러에 대한 예측을 하고, 처리하기 위해 예외 처리를 사용한다.
예외 처리 사용
DECLARE
vname varchar2(5);
BEGIN
dbms_output.put_line('하나');
SELECT name INTO vname FROM tblInsa WHERE num = 1001;
dbms_output.put_line('둘');
dbms_output.put_line(vname);
EXCEPTION
WHEN OTHERS THEN --모든 에러 처리
dbms_output.put_line('예외 처리');
END;
try-catch문으로 치면 begin부터 exception까지가 try절, exceoption부터 end까지가 catch절로 이해할 수 있다.
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('예외 처리');
이 부분이 하나의 catch절이다.
예외를 테이블에 저장
run-time 에러에는 내가 예측하지 못한 에러도 포함되어 있기 때문에 버그를 모두 잡아내기 힘들다.
그래서 예외가 발생하면 예측하지 못한 에러가 발생했는지 확인할 수 있도록 발생한 에러를 DB에 저장한다.
예외가 발생하면 DB에 저장할 수 있게 log 테이블을 만들어 보도록 하자.
에러 상태 코드
CREATE TABLE tblLog (
seq NUMBER PRIMARY KEY, --PK
code varchar2(7) NOT NULL CHECK (code IN ('A001', 'B001', 'B002', 'C001')), --에러 상태 코드
message varchar2(1000) NOT NULL, --에러 메시지
regdate DATE DEFAULT sysdate NOT NULL --에러 발생 시각
)
CREATE SEQUENCE seqLog;
발생할 수 있는 에러를 예측하여 만든 게 에러 상태 코드라고 한다.
실제로는 발생할 수 있는 에러 종류가 너무 많기 때문에 연습용으로 체크를 했지만, 실제로 작업할 때에는 이와 같이 사용하지 않도록 한다.
이렇게 테이블을 만들어두면 관리자가 모니터링을 하고 있지 않더라도 에러가 발생했다는 것을 알 수 있다.
예외 처리 구분
DECLARE
vcnt NUMBER;
vname tblInsa.name%TYPE;
BEGIN
--ORA-01476: divisor is equal to zero
SELECT count(*) INTO vcnt FROM tblCountry WHERE name = '태국';
dbms_output.put_line(100 / vcnt);
--ORA-01403: no data found
SELECT name INTO vname FROM tblInsa WHERE num = '1000';
dbms_output.put_line(vname);
END;
위 소스코드에서는 divisor is equal to zero 에러와 no data found 에러가 발생하고 있다.
exception은 오류를 구분하여 출력하는 게 가능한데, 공식 문서에서 데이터를 찾아서 예외 처리를 해야 한다.
오라클 공식 도큐먼트
https://docs.oracle.com/cd/E11882_01/timesten.112/e21639/exceptions.htm#TTPLS195
공식 문서에서 오라클에서 인식 가능한 에러 종류를 확인할 수 있다.
이중 Exception name와 Oracle Database error number를 사용하므로 기억해 두도록 한다.
Exception name 검색
ORA-01476, ORA-01403 오류에 번호가 적혀 있다. 이게 바로 Oracle Database error number이다.
이를 공식 문서에서 찾아서 exception에 Exception name을 적어주면 된다.
예외를 테이블에 저장
DECLARE
vcnt NUMBER;
vname tblInsa.name%TYPE;
BEGIN
--ORA-01476: divisor is equal to zero
SELECT count(*) INTO vcnt FROM tblCountry WHERE name = '태국';
dbms_output.put_line(100 / vcnt);
--ORA-01403: no data found
SELECT name INTO vname FROM tblInsa WHERE num = '1000';
dbms_output.put_line(vname);
EXCEPTION
WHEN ZERO_DIVIDE THEN
dbms_output.put_line('0으로 나누기');
INSERT INTO tblLog
VALUES (seqLog.nextVal, 'B001', '가져온 레코드가 없습니다.', default);
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('데이터 없음');
INSERT INTO tblLog
VALUES (seqLog.nextVal, 'A001', '직원이 존재하지 않습니다.', default);
WHEN OTHERS THEN --모든 에러 처리
dbms_output.put_line('나머지 예외');
INSERT INTO tblLog
VALUES (seqLog.nextVal, 'C001', '기타 예외가 발생했습니다.', default);
END;
전용 구문을 만들었기 때문에 여러 에러에 대한 대처가 가능하다.
영구적으로 데이터베이스에 예외 내용을 insert 하여 저장하여 관리할 수 있다.