Skip to content
isdnetworks
Go back

값은 옮겼는데 코드 체계가 달랐다

옛 게시판 데이터 8만 건을 새 시스템으로 옮기는 일을 받았다. 컬럼 이름을 맞춰서 넣었더니 개수도 맞고 오류도 없는데 화면에서 분류가 전부 미분류로 나왔다.

Table of contents

Open Table of contents

코드 체계가 달랐다

양쪽 분류 컬럼의 값을 뽑아 봤다. 옛 쪽은 BBS_NOTICEBBS_FREE처럼 접두사가 붙은 대문자였고 새 쪽은 noticefree 같은 소문자였다. 새 쪽에는 event가 있는데 옛 쪽에는 없기도 했다.

값을 그대로 옮겼으니 BBS_NOTICE가 그대로 들어갔고, 화면 코드는 notice를 찾으니 아무것도 안 맞는다. 컬럼 이름이 맞고 개수가 맞아도 값의 체계가 다르면 옮긴 것이 아니었다.

대응표를 만들었다

바로 변환 규칙을 짜고 싶어졌는데 규칙으로 되는 것이 아니었다. 분류 컬럼은 접두사를 떼고 소문자로 바꾸면 맞지만 상태 컬럼은 그렇지 않았다.

STAT_01 → open
STAT_02 → closed
STAT_03 → hidden
STAT_09 → deleted

숫자와 이름 사이에 규칙이 없다. 표가 필요했다. 옛 코드와 새 코드와 코드 종류를 담는 표를 만들고 조인으로 변환했다.

INSERT INTO board (board_no, category, status, title, content)
SELECT o.no, m1.new_code, m2.new_code, o.title, o.content
FROM old_board o
LEFT JOIN code_map m1 ON m1.code_type='category' AND m1.old_code = o.cate_cd
LEFT JOIN code_map m2 ON m2.code_type='status'   AND m2.old_code = o.stat_cd;

표에 없는 값

LEFT JOIN이라 표에 없는 값은 조용히 NULL이 된다. 넣기 전에 없는 값부터 찾았다.

SELECT DISTINCT o.cate_cd
FROM old_board o
LEFT JOIN code_map m ON m.code_type='category' AND m.old_code = o.cate_cd
WHERE m.new_code IS NULL;

두 개가 나왔다. BBS_TEMP는 임시 게시판이라 새 시스템에 대응이 없고, 빈 문자열은 옛날 데이터에 분류가 안 들어간 것이었다. 이 조회를 안 했으면 8만 건 중 몇백 건이 조용히 빈 값으로 들어갔을 것이다.

대응이 없을 때의 선택

세 가지 중에 골라야 했다. 안 옮기면 데이터가 사라지고, 기본값으로 옮기면 원래 분류를 잃고, 새 코드를 만들면 새 시스템에 안 쓰는 분류가 생긴다.

BBS_TEMP는 안 옮기되 따로 백업 테이블에 남겼다. 빈 문자열은 기본 분류로 넣고 그 행 목록을 파일로 남겼다. 어느 쪽을 고르든 무엇을 어떻게 처리했는지 기록이 남게 하는 것이 중요해 보였다.

분류별로 세어 봤다

옮기고 나서 양쪽을 분류별로 세어 짝지어 비교했다. 한 분류에서 12건이 비었다.

찾아보니 제목이 비어 있는 행이 있었고 새 테이블의 제목 컬럼이 NOT NULL 이었다. 그런데 INSERT ... SELECT 가 멈추지도 않고 그 행만 빠졌다. 어느 쪽이 될지는 sql_mode 가 정한다. 엄격이면 오류로 멈추고 아니면 빈 값이 들어가면서 경고만 난다. 둘 다 아닌 것은 IGNORE 를 붙였기 때문이었다. 오류가 경고로 낮아지고 그 행만 빠진다. 전체 개수만 봤으면 8만과 7만9988이라 눈에 안 띄었을 텐데 분류별로 세니까 어디서 빠졌는지가 보였다.

옮기다 중간에 문제가 나면 다시 돌려야 하는데 그대로 돌리면 중복이 들어간다. 옛 식별자를 새 테이블에 그대로 넣고 유일 키를 걸어서 이미 들어간 것은 무시되게 했다. 그러면 몇 번을 돌려도 결과가 같다.

정리


Share this post on:

Previous Post
지우고 다시 만들다 더 나빠졌다
Next Post
처리 중에 바뀌는 대상 집합