데이터 변환
마스킹, 변경 이력 적재, 코드와 날짜 변환 및 타깃 변환과 소스 제외의 차이
#핵심 요약
실습에서는 Replicat COLMAP으로 이름 일부 표시, 급여 등급화, 변경 이력 적재, 부서 코드와 날짜 형식 변환을 실습함
타깃 변환만 하면 원래 값은 트레일에 남으므로 전송 자체를 제외할 컬럼은 Extract에서 제외하는 것으로 구분함
이력 적재는 보충 로깅과 행 이미지 수집, INSERTALLRECORDS와 변경 메타데이터 매핑을 함께 구성함
#개념과 동작 원리
| 함수와 옵션 | 변환 및 이력 적재 동작 |
|---|---|
| @STREXT, @STRCAT | 이름 일부와 별표를 이어 표시 |
| @IF, @COLTEST | 급여 등급 분기와 NULL, MISSING 확인 |
| @CASE | 부서, 회원 등급 코드 대응과 기본값 지정 |
| @DATE | 날짜를 YYYYMMDD 문자열로 변환 |
| @GETENV | 연산 종류, 커밋 시각, CSN을 가져옴 |
| INSERTALLRECORDS | UPDATE, DELETE를 포함한 변경을 타깃 이력 행으로 추가 |
| NOCOMPRESSUPDATES, NOCOMPRESSDELETES | 이력에 필요한 전체 행 이미지를 위한 Extract 설정으로 제시 |
실습에서는 현재 상태용 테이블과 이력용 테이블을 분리하며 이력 테이블에는 같은 사원번호가 반복되므로 사원번호 단독 PK를 두지 않음
실습에서는 이 구조를 SCD Type 2라고 부름
유효기간과 현재 행 관리가 기재되지 않아 변경 이력 적재만 설명함
#필수 명령어 또는 SQL
MAP scott.emp, TARGET scott.emp_dw,
COLMAP (
EMP_ID = EMPNO,
EMP_NAME = @STRCAT (@STREXT (ENAME, 1, 1), '***'),
JOB_TITLE = JOB,
SAL_GRD = @IF (SAL >= 3000, 'A', @IF (SAL >= 1500, 'B', 'C')),
DEPT_ID = DEPTNO
);결과 해석: 실습에서는 이름 첫 글자와 별표, 급여 A, B, C 등급을 기대하며 실제 조회 표는 해당 절에 기재 없음 실습의 NULL, MISSING 대안 식은 중간 등급 B가 빠져 있어 기본 식과 같은 등급 규칙이라고 사용할 수 없음
ADD SCHEMATRANDATA scott ALLCOLSNOCOMPRESSUPDATES
NOCOMPRESSDELETES
GETUPDATEBEFORES결과 해석: 실습에서는 변경되지 않은 컬럼과 DELETE의 키 이외 값도 이력에 남기기 위한 설정으로 설명하며 실제 트레일 판독 출력은 기재 없음
MAP scott.emp, TARGET scott.emp_hist,
INSERTALLRECORDS,
COLMAP (
USEDEFAULTS,
OP_TYPE = @CASE (@GETENV ('GGHEADER', 'OPTYPE'),
'INSERT', 'INSERT',
'DELETE', 'DELETE',
'UPDATE'),
CHG_TS = @GETENV ('GGHEADER', 'COMMITTIMESTAMP'),
CHG_CSN = @GETENV ('TRANSACTION', 'CSN'),
SRC_SYS = '<DB_NAME>'
);결과 해석: 주석 표에는 INSERT, UPDATE, DELETE 세 이력이 남고 현재 EMP에는 해당 행이 사라진 것으로 제시됨
실습에서는 OPTYPE의 SQL COMPUPDATE, PK UPDATE를 UPDATE로 분류함
긴 문자열이 잘리는지는 오류 출력이 없어 확인 불가
CSN으로 정렬하는 예제지만 같은 트랜잭션의 여러 행은 동일 CSN이라고 다른 시나리오에 적혀 있어 모든 변경의 순서를 CSN 하나로 확정하는 범위는 확인 불가
MAP scott.emp, TARGET scott.emp_std,
COLMAP (
EMP_ID = EMPNO,
EMP_NAME = ENAME,
DEPT_CD = @CASE (DEPTNO, 10, 'ACC', 20, 'RND', 30, 'SAL', 'ETC'),
HIRE_YMD = @DATE ('YYYYMMDD', 'YYYY-MM-DD HH:MI:SS', HIREDATE)
);결과 해석: 실습에서는 부서 20을 RND, 나열하지 않은 부서를 ETC로 바꾸는 예제를 제시함
날짜 출력은 주석의 예시임
SYSDATE 입력값은 실행 시각에 따라 달라짐
#이력 테이블과 확인
CREATE TABLE emp_hist (
op_type VARCHAR2(10),
chg_ts VARCHAR2(30),
chg_csn NUMBER,
src_sys VARCHAR2(10),
empno NUMBER(4),
ename VARCHAR2(10),
job VARCHAR2(9),
sal NUMBER(7,2),
deptno NUMBER(2)
);SELECT op_type, chg_csn, chg_ts, empno, ename, sal
FROM emp_hist
WHERE empno = <EMPNO>
ORDER BY chg_csn;결과 해석:
이력 테이블에 PK를 걸면 같은 사원번호의 두 번째 변경이 ORA-00001로 멈추므로, 대리키(시퀀스, IDENTITY)를 쓰거나 키를 두지 않음
GoldenGate는 기본으로 UPDATE 때 바뀐 컬럼과 키만, DELETE 때 키만 트레일에 써서, 전체 행 이미지 없이 이력에 넣으면 안 바뀐 컬럼이 NULL이 됨NOCOMPRESSDELETES를 빠뜨리면 DELETE 이력 행만 이름, 급여가 NULL로 들어옴
실습 기록: 소스에서 한 사원을 INSERT, UPDATE(급여 1000 → 2000), DELETE하고 각각 커밋하자 이력에 INSERT, UPDATE, DELETE 세 행이 CSN 오름차순으로 쌓였고, INSERT와 UPDATE의 CHG_TS는 소수점 이하까지 같았지만 CHG_CSN으로 순서가 갈렸음
운영 emp에서는 그 사원이 사라졌지만 이력은 남아, Data Guard처럼 소스와 똑같아야 하는 구조로는 만들 수 없는 결과임
같은 방식으로 휴대폰 가운데 자리 같은 값도 @STRCAT (@STREXT (PHONE, 1, 3), '-****-', @STREXT (PHONE, 10, 13))처럼 가린다고 수업 자료는 예를 듦
@CASE에 기본값을 주지 않으면 나열하지 않은 값은 NULL이 됨(실습은 40번 부서가 ETC)
타깃 컬럼을 DATE로 두면 @DATE 변환이 필요 없으므로 문자열이 꼭 필요할 때만 씀
큰따옴표로 문자열을 쓴 실수로 REP1이 ABENDED 되면, 파라미터만 고치고 START REPLICAT하면 트레일에 남은 레코드가 다시 적용되므로 소스에 다시 INSERT하지 않음(중복 시 ORA-00001)
#사용 조건과 주의사항
실습에서는 문자열은 작은따옴표, 컬럼명은 큰따옴표로 구분하며(12.2부터 USEANSISQLQUOTES 기본이라고 설명) 큰따옴표 문자열은 OGG-01298, OGG-00919로 ABENDED 된다고 적음
버전별 기본값은 확인 불가
날짜 형식은 입력 표현과 맞아야 하며 변환 오류는 REP1 리포트에서 확인하도록 적음
시나리오1은 신규 회원 테이블을 현재, 이력 테이블로 나누고 비밀번호 컬럼 제외와 타깃 별표 상수 매핑을 조합함
트레일 검색은 예상 결과만 있으며 실제 정보 유출 여부는 확인 불가
ALLCOLS 원상복구는 문서마다 ADD만 사용하는 경우와 DELETE 후 ADD하는 경우가 달라 일반 변경 절차로 확정할 수 없음