운영 중인 테이블을 손대기 전에 백업용 사본을 하나 떠 두거나, 같은 구조의 테이블을 하나 더 만들어야 할 때가 자주 있습니다. 쇼핑몰 테이블을 복제한다면 저는 이런 식으로 씁니다.

Create Table shop_03 like `shop`

테이블을 복사하는 방법은 크게 세 가지인데, 겉보기엔 비슷해도 결과물이 꽤 다릅니다. 무엇이 따라오고 무엇이 빠지는지를 알고 골라야 나중에 "왜 PK가 없지?" 하고 당황하지 않습니다.

빈 껍데기만 필요할 때: LIKE

Create Table new_table like old_table

LIKE 는 원본 테이블의 정의를 그대로 가져옵니다. 컬럼 타입은 물론 기본 키, 인덱스, AUTO_INCREMENT 속성까지 원래 설정대로 만들어지고, 데이터는 한 줄도 들어가지 않습니다. 같은 구조의 월별 테이블이나 테스트용 테이블을 만들 때 가장 무난한 방법입니다.

스크립트로 여러 번 돌릴 거라면 이미 있을 때 에러가 나지 않도록 조건을 붙여 두면 편합니다.

Create Table IF NOT EXISTS new_table like old_table

참고로 큐브리드(CUBRID)에서는 원본 테이블에 Primary Key 나 auto_increment 가 걸려 있으면 이 방식으로 복사가 되지 않는다고 하니, MySQL 문법을 그대로 옮겨 쓸 때는 확인이 필요합니다.

데이터까지 한 번에: CREATE TABLE ... SELECT

Create Table new_table ( select * from old_table )

조회 결과를 그대로 새 테이블로 만드는 방식이라 구조와 데이터가 함께 생깁니다. 작업 전에 "현재 상태를 통째로 떠 두자"고 할 때 빠릅니다.

대신 함정이 있습니다. 새 테이블의 컬럼은 SELECT 결과를 기준으로 만들어지기 때문에 원본의 Primary Key 나 auto_increment 설정은 따라오지 않고 값만 복사됩니다. 인덱스도 마찬가지로 빠집니다. 백업 용도로만 잠깐 쓸 거면 상관없지만, 이 사본을 실제 서비스용으로 쓸 생각이라면 키와 인덱스를 다시 걸어 줘야 합니다. 구조는 LIKE 로 먼저 만들고 데이터는 아래 INSERT ... SELECT 로 채우는 조합이 더 안전한 이유가 이겁니다.

이미 있는 테이블에 부어 넣기: INSERT INTO ... SELECT

원문에 적힌 형태는 이렇습니다.

Insert Into destination_table ( select * form source_table)

여기서 form 은 from 의 오타라 그대로 실행하면 문법 오류가 납니다. 바로잡은 쿼리는 아래와 같습니다.

Insert Into destination_table ( select * from source_table)

대상 테이블에 자동 증가 컬럼이 있고, 복사해 오는 값 중에 대상 테이블에 이미 있는 값과 겹치는 게 있으면 중복 키 오류로 멈춥니다. 빈 테이블로 옮길 때는 문제없지만, 데이터가 들어 있는 테이블에 합칠 때는 이 부분을 먼저 확인해야 합니다.

필요한 컬럼만 골라 옮길 수도 있습니다. 대상 테이블의 컬럼 목록과 SELECT 하는 컬럼의 순서만 맞춰 주면 됩니다.

Insert Into destination_table (column_a, column_b) (select a, b from source_table)

이 형태를 쓰면 자동 증가 컬럼은 목록에서 빼서 새 번호를 받게 하고 나머지 값만 옮기는 식으로 중복 문제도 피할 수 있습니다. 구조가 조금 다른 테이블 사이에서 데이터를 이관할 때도 컬럼 이름을 하나씩 짝지어 주면 되니 저도 이 형태를 제일 많이 씁니다.

참고: kilsu1024 님 블로그 글