Programming/Oracle

[Oracle] PL/SQL 예외 처리 (Exception Handling)

Isaac S. Lee 2023. 9. 7. 17:10

💡예외 처리


예외 처리는 실행부에서(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

 

Errors and Exception Handling

8/14 4 Errors and Exception Handling This chapter describes the flexible error trapping and error handling you can use in your PL/SQL programs. For more information on error-handling and exceptions in PL/SQL, see "PL/SQL Error Handling" in Oracle Database

docs.oracle.com

공식 문서에서 오라클에서 인식 가능한 에러 종류를 확인할 수 있다.

이중 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 하여 저장하여 관리할 수 있다.