테마
본사 레거시 유통의 「일 재고 마감」 프로시저는 매일 23:30에 그날 판매 수량만큼 매장 재고를 빼고, 날짜별 백업 테이블을 떠 두고, 리포트용 재고표를 채운다. 운영 문서에는 "실패하면 예외 처리부에서 ROLLBACK하므로 처음 상태로 돌아간다"라고 적혀 있다. 12월 30일 밤 마감이 실패했다. 다음 날 아침 운영자가 원인(분류가 비어 있는 신상품)을 고치고 다시 돌렸는데 또 실패했고, 백업 테이블을 지운 뒤 세 번째로 돌려 성공했다. 그날 오후 매장 여섯 곳에서 전화가 왔다. "전산 재고가 실제보다 한참 적어요."
CF18 일별상품재고: 408행 · 6블록 · PK (SHP_NO, ITM_NO, INV_BS_DT) · 매장과 상품마다 그날 재고 한 행CF10 판매: 500,000행 · 4,583블록 · SLE_DT VARCHAR2(8) · SHP_NO / CF11 판매상품: 1,096,708행 · 8,204블록 · CF11_PK (SLE_NO, ITM_NO)CF01 상품: 109행 · 12월 30일에 CTG_NO가 비어 있는 신상품 하나가 등록됐다 / CF02 카테고리: 18행CF18_RPT 리포트용 재고표(문제 설정): CTG_NM이 NOT NULL이다 / CF_CLOSE 마감 관리(문제 설정): 날짜마다 한 행 · CLOSE_YNPROCEDURE P_DAY_CLOSE(p_dt VARCHAR2) IS
BEGIN
-- ① 그날 판매 수량만큼 재고를 뺀다
UPDATE CF18 s
SET s.INV_QTY = s.INV_QTY - (SELECT NVL(SUM(d.SLE_QTY), 0)
FROM CF10 h JOIN CF11 d ON d.SLE_NO = h.SLE_NO
WHERE h.SLE_DT = p_dt AND h.SHP_NO = s.SHP_NO AND d.ITM_NO = s.ITM_NO)
WHERE s.INV_BS_DT = p_dt;
-- ② 날짜별 백업 테이블
EXECUTE IMMEDIATE 'CREATE TABLE CF18_BAK_' || p_dt
|| ' AS SELECT * FROM CF18 WHERE INV_BS_DT = ''' || p_dt || '''';
-- ③ 리포트용 재고표
INSERT INTO CF18_RPT (SHP_NO, ITM_NO, INV_BS_DT, INV_QTY, CTG_NM)
SELECT s.SHP_NO, s.ITM_NO, s.INV_BS_DT, s.INV_QTY, g.CTG_NM
FROM CF18 s
JOIN CF01 i ON i.ITM_NO = s.ITM_NO
LEFT JOIN CF02 g ON g.CTG_NO = i.CTG_NO
WHERE s.INV_BS_DT = p_dt;
-- ④ 마감 표시
UPDATE CF_CLOSE SET CLOSE_YN = 'Y' WHERE CLOSE_DT = p_dt;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK; -- 실패하면 처음 상태로 (운영 문서)
RAISE;
END;
[12월 30일 · 31일 실행 기록 — 스케줄러와 알림 로그]
회 시각 단계 결과
1 12/30 23:30 ① UPDATE CF18 (408행) 끝
② CREATE TABLE CF18_BAK_20231230 끝
③ INSERT CF18_RPT ORA-01400: cannot insert NULL into ("PUP"."CF18_RPT"."CTG_NM")
예외 처리부 ROLLBACK · RAISE → 스케줄러 FAILED
2 12/31 08:40 (신상품 분류를 채운 뒤) ① 끝
② ORA-00955: name is already used by an existing object
예외 처리부 ROLLBACK · RAISE → FAILED
3 12/31 08:52 (CF18_BAK_20231230 을 DROP 한 뒤) ① ② ③ ④ COMMIT → SUCCEEDED
[12월 31일 09:10 — 매장 001 · 상품 셋 · CF18 (INV_BS_DT = '20231230')]
ITM_NO 마감 전 재고 그날 판매 지금 INV_QTY 있어야 할 값
1000021 140 22 74 118
1000037 88 15 43 73
1000102 61 9 34 52
(매장 여섯 곳 합계: 그날 판매 2,140개 · 있어야 할 값보다 덜 남은 재고 4,280개)
[연습 DB 에서 다시 잰 것 — 교재 12화 실습/01 [E] 와 같은 모양]
INSERT → CREATE TABLE (성공) → ROLLBACK INSERT 가 남았다
INSERT → CREATE TABLE (ORA-00955 로 실패) → ROLLBACK INSERT 가 남았다