오늘은 간단하게 백업 프로시저 + 프로시저 동작 구동 확인을 위한 로깅 테이블을 구현해 봤습니다.
오렌지가 아닌 디비버라 텍스트로 DDL만 보여 드립니다 ㅠ.ㅠ
CREATE TABLE "ALEXPARK"."P_LOG"
( "STATUS" NUMBER,
"PROC_DATE" CHAR(8),
"PROC_TIME" CHAR(10),
"ETC" VARCHAR2(2000)
)
테스트 목적이니 간략하게 위와 같이 구성해 보았고,
STATUS는 특정 0 작업중, 9 작업완료 특이사항 없음, -1 특이사항 발생 (숫자는 그냥 임의로 ^^,,)
PROC_DATE와 PROC_TIME의 경우 시퀸스를 활용하면 더 구체적이겠지만, 밀리초 정도로도 충분히 테스트용으로는 구분인자가 확실하기에 PROC_DATE||PROC_TIME으로
[20250615222108.298] 와 같이 고유 ID를 구성
ETC는 특이사항 기록용 칼럼으로 활용하였습니다.
--SOURCE TBL1
CREATE TABLE alexpark.p_tbl0 (a number);
--SOURCE TBL2
CREATE TABLE alexpark.p_tbl1 (a number);
--TARGET TBL
CREATE TABLE alexpark.p_tbl2 (a number);
테이블과 데이터 적당히 삽입한뒤, P_TBL2를 백업용 테이블이라 가정하였습니다.
여러개의 테이블을 하나의 프로시저에서 백업한다고 가정하고
SELECT STATUS INTO W3 FROM alexpark.p_log WHERE STATUS=-1;
EXEPTION 테스트를 위해서 간소화 하였지만, 과거 일자의 로그와 대조하여 불일치 할경우 EXEPTION으로 뺄수도 있고,
또는 이미 백업되어 있을경우, 해당일자의 테이블명을 SELECT간 TOO_MANY_ROWS 로 예외처리가 가능한 무궁무진한 예외처리의 세계..
일단 프로시저는 아래와 같이 구성했고
CREATE OR REPLACE PROCEDURE p_pro (
i_1 IN VARCHAR2,
i_2 IN NUMBER
)
IS
w1 VARCHAR2(2000);
w2 NUMBER;
wcnt NUMBER;
v_proc_date CHAR(8);
v_proc_time CHAR(10);
W3 NUMBER;
v_error_msg VARCHAR2(4000);
BEGIN
------------------------------------
------------------p_tbl1 백업
------------------------------------
BEGIN
w1 := i_1;
w2 := i_2;
wcnt := 0;
v_proc_date := TO_CHAR(SYSDATE, 'YYYYMMDD');
v_proc_time := TO_CHAR(SYSTIMESTAMP, 'HH24MISS.FF3');
INSERT INTO alexpark.p_log (status, etc, proc_date, proc_time)
VALUES (0, '', v_proc_date, v_proc_time);
SELECT COUNT(*)
INTO wcnt
FROM alexpark.p_tbl1;
SELECT STATUS INTO W3 FROM alexpark.p_log WHERE STATUS=-1;
IF wcnt > 0 THEN
INSERT INTO alexpark.p_tbl2
SELECT * FROM alexpark.p_tbl1;
-- 특정 로그 레코드만 업데이트
UPDATE alexpark.p_log
SET status = 12,
etc = wcnt || ' inserted'
WHERE proc_date = v_proc_date
AND proc_time = v_proc_time;
COMMIT;
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
UPDATE alexpark.p_log
SET status = -1,
etc = 'DATA_NOT_FOUND'
WHERE proc_date = v_proc_date
AND proc_time = v_proc_time;
WHEN OTHERS THEN
v_error_msg := SQLERRM;
UPDATE alexpark.p_log
SET status = -1,
etc = v_error_msg
WHERE proc_date = v_proc_date
AND proc_time = v_proc_time;
END;
------------------------------------
------------------p_tbl0 백업
------------------------------------
BEGIN
w1 := i_1;
w2 := i_2;
wcnt := 0;
v_proc_date := TO_CHAR(SYSDATE, 'YYYYMMDD');
v_proc_time := TO_CHAR(SYSTIMESTAMP, 'HH24MISS.FF3');
INSERT INTO alexpark.p_log (status, etc, proc_date, proc_time)
VALUES (0, '', v_proc_date, v_proc_time);
SELECT COUNT(*)
INTO wcnt
FROM alexpark.p_tbl0;
IF wcnt > 0 THEN
INSERT INTO alexpark.p_tbl2
SELECT * FROM alexpark.p_tbl0;
UPDATE alexpark.p_log
SET status = 9,
etc = wcnt || wcnt||' inserted'
WHERE proc_date = v_proc_date
AND proc_time = v_proc_time;
COMMIT;
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
UPDATE alexpark.p_log
SET status = -1,
etc = 'DATA_NOT_FOUND'
WHERE proc_date = v_proc_date
AND proc_time = v_proc_time;
WHEN OTHERS THEN
v_error_msg := SQLERRM;
UPDATE alexpark.p_log
SET status = -1,
etc = v_error_msg
WHERE proc_date = v_proc_date
AND proc_time = v_proc_time;
END;
END;
간단하게 NOTEPAD로 BEGIN END 묶인 부분을 보여주면 각각 테이블 별 BEGIN을 묶고 전체 프로시저의 BEGIN으로 나누었다.

이를 통해 실행시켜보면 실행 1회차엔 P_LOG 테이블내 STATUS -1값이 존재하지 않기 때문에 실패하며
NOTFOUND 예외처리로 잘 빠졌지만

실행 2회차에는 -1값이 보이며 빠지지 않고 두개의 백업 테이블이 수행되는 모습이다

JOB으로 등록해두고 P_LOG 테이블에 일백업/일삭제 프로시저를 각기 등록한뒤
조건절을 잘 추가한다면 삭제하려는 대상 일자에 백업기록이 없거나 정상 종료되지 못한 테이블에 대하여 삭제하는 사고를 예방할 수 있을것 같다.
그렇다 그냥 EXEPTION 공부하면서 일백업 일삭제라는 거창한 이름을 붙인 포스팅이였던것,,,
회사를 다니며 부족한 부분을 많이 알게되고 공부한 내용을 기록하는 차원에서 꾸준히 포스팅 해봐야겠다
'DB > SQL' 카테고리의 다른 글
| [SQL] v$session으로 세션 강제 종료하기 (0) | 2023.09.15 |
|---|---|
| Redo Log 사이즈 변경하기 (0) | 2023.09.13 |
| [SQL] like % _ escape 문 (0) | 2023.08.08 |
| 유저 생성 , 권한 부여 , 수정 (ORACLE, TIBERO) (0) | 2023.07.12 |
| mysql 명령어 (0) | 2021.06.21 |