PL/SQL 코드를 작성 시 발생할 수 있는 오류
EXCEPTION WHEN 예외명1 THEN 예외처리 구문1
WHEN 예외명2 THEN 예외처리 구문2
...
;
아래 예제를 통해 DIVISION 에러를 발생시켜보자.
SET SERVEROUTPUT ON;
DECLARE
vi_num number := 0;
BEGIN
vi_num := 10 /0;
dbms_output.put_line('success!!');
EXCEPTION when others then
dbms_output.put_line('오류가 발생했습니다');
END;
SET SERVEROUTPUT ON;
DECLARE
vi_num number := 0;
BEGIN
vi_num := 10 /0;
dbms_output.put_line('success!!');
EXCEPTION when others then
dbms_output.put_line('오류가 발생했습니다');
END;
/
SET SERVEROUTPUT ON;
CREATE OR REPLACE PROCEDURE ch10_exception_proc
IS
vi_num NUMBER := 0;
BEGIN
vi_num := 10 / 0;
DBMS_OUTPUT.PUT_LINE('Success!');
EXCEPTION WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('오류가 발생했습니다');
END;
/
SET SERVEROUTPUT ON;
declare
vi_num number := 0;
begin
ch10_exception_proc;
dbms_output.put_line('Success!');
end;
SQLCODE
SQLERRM
- 예외 정의 : 사용자정의예외명 EXCEPTION;
- 예외 발생 :RAISE 사용자정의예외명;
- 발생된 예외 처리 :EXCEPTION WHEN 사용자정의예외명 THEN ...
select count(*)
시스템 예외에는 ZERO_DIVIDE, INVALID_NUMBER 같이 미리 정의된 예외가 있었다. 하지만 이들처럼 예외명이 부여된 것은 시스템 예외 중 극소수이고 나머지는 예외코드만 존재한다.
예외 이름이 없는 이런 예외에 이름을 부여하면 코드가 훨씬 읽기 편할 뿐만 아니라, 해당 코드의 ㅗㄹ직을 파악하는 것도 아주 쉬워진다.
CREATE OR REPLACE PROCEDURE ch10_ins_emp_proc (
p_emp_name employees.emp_name%TYPE,
p_department_id departments.department_id%TYPE,
p_hire_month VARCHAR2 )
IS
vn_employee_id employees.employee_id%TYPE;
vd_curr_date DATE := SYSDATE;
vn_cnt NUMBER := 0;
ex_invalid_depid EXCEPTION; -- 잘못된 부서번호일 경우 예외 정의
ex_invalid_month EXCEPTION; -- 잘못된 입사월인 경우 예외 정의
PRAGMA EXCEPTION_INIT ( ex_invalid_month, -1843); -- 예외명과 예외코드 연결
BEGIN
-- 부서테이블에서 해당 부서번호 존재유무 체크
SELECT COUNT(*)
INTO vn_cnt
FROM departments
WHERE department_id = p_department_id;
IF vn_cnt = 0 THEN
RAISE ex_invalid_depid; -- 부서코드 사용자 정의 예외 발생
END IF;
-- 입사월 체크(1~12월 범위를 벗어났는지 체크)
IF SUBSTR(p_hire_month, 5, 2) NOT BETWEEN '01' AND '12' THEN
RAISE ex_invalid_month; -- 잘못된 입사월 사용자 정의 예외 발생
END IF;
-- employee_id의 max 값에 +1
SELECT MAX(employee_id) + 1
INTO vn_employee_id
FROM employees;
-- 사용자예외처리 예제이므로 사원 테이블에 최소한 데이터만 입력함
INSERT INTO employees ( employee_id, emp_name, hire_date, department_id )
VALUES ( vn_employee_id, p_emp_name, TO_DATE(p_hire_month || '01'), p_department_id );
COMMIT;
EXCEPTION
WHEN ex_invalid_depid THEN -- 사용자 정의 예외 처리
DBMS_OUTPUT.PUT_LINE('해당 부서번호가 없습니다');
WHEN ex_invalid_month THEN -- 입사월 사용자 정의 예외 처리
DBMS_OUTPUT.PUT_LINE(SQLCODE);
DBMS_OUTPUT.PUT_LINE(SQLERRM);
DBMS_OUTPUT.PUT_LINE('1~12월 범위를 벗어난 월입니다');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
CREATE TABLE app_user_define_error (
error_code NUMBER, -- 에러코드
error_message VARCHAR2(300), -- 에러 메시지
create_date DATE DEFAULT SYSDATE, -- 등록일자
PRIMARY KEY (error_code)
);
INSERT INTO app_user_define_error ( error_code, error_message )
VALUES (-1843, '지정한 월이 부적합합니다');
INSERT INTO app_user_define_error ( error_code, error_message )
VALUES (-20000, '해당 부서가 없습니다');
COMMIT;