SQL Server 데이터 관리의 핵심: SELECT INTO vs INSERT INTO 완벽 분석
데이터베이스를 운영하다 보면 기존 데이터를 활용해 새로운 테이블을 만들거나, 이미 존재하는 테이블에 데이터를 대량으로 삽입해야 하는 상황이 빈번하게 발생합니다. MS-SQL(MSSQL) 환경에서 이러한 작업을 수행할 때 가장 대표적으로 사용되는 두 가지 방식이 바로 SELECT INTO와 INSERT INTO SELECT입니다.
두 구문은 ‘데이터를 복사하여 넣는다’는 근본적인 목적은 같지만, 동작 방식과 제약 사항, 그리고 성능 면에서 뚜렷한 차이를 보입니다. 오늘 포스팅에서는 개발자나 데이터베이스 관리자(DBA)가 상황에 맞는 최적의 선택을 할 수 있도록 두 구문의 특징을 상세히 비교해 드리겠습니다.

1. SELECT INTO: 새로운 테이블의 탄생
SELECT INTO 구문은 쿼리 실행 시점에 새로운 테이블을 생성함과 동시에 조회된 데이터를 해당 테이블에 삽입하는 방식입니다.
주요 특징
- 자동 테이블 생성: 대상 테이블이 미리 존재하지 않아도 됩니다. 쿼리 결과의 스키마를 바탕으로 테이블이 즉석에서 만들어집니다.
- 스키마 복사: 소스 테이블의 컬럼 이름, 데이터 타입, Null 허용 여부 등을 그대로 가져옵니다.
- 제약 사항: 하지만 PK(Primary Key), FK(Foreign Key), 인덱스(Index), 제크 제약 조건 등은 복사되지 않습니다. 오직 데이터 구조와 값만 복사됩니다.
- 성능: 대량의 데이터를 빠르게 복사할 때 유리합니다. 로그를 최소화하는 방식으로 동작할 수 있기 때문입니다.
기본 문법
SQL
SELECT 컬럼1, 컬럼2, ...
INTO 새로운_테이블_이름
FROM 기존_테이블_이름
WHERE 조건;
2. INSERT INTO SELECT: 기존 테이블로의 데이터 수혈
반면, INSERT INTO SELECT 구문은 이미 생성되어 있는 테이블에 데이터를 추가할 때 사용합니다.
주요 특징
- 기존 테이블 활용: 데이터를 넣을 대상 테이블(Target Table)이 미리 존재해야 합니다.
- 구조 일치 필요: 삽입하려는 데이터의 컬럼 개수와 데이터 타입이 대상 테이블의 정의와 일치해야 합니다.
- 제약 조건 준수: 대상 테이블에 설정된 PK나 Unique 인덱스 등 모든 제약 조건을 체크하므로 데이터 무결성을 보장하기 좋습니다.
- 유연성: 특정 컬럼만 선택해서 넣거나, 복잡한 JOIN 결과를 기존 테이블에 덧붙일 때 유용합니다.
기본 문법
SQL
INSERT INTO 대상_테이블 (컬럼1, 컬럼2, ...)
SELECT 컬럼1, 컬럼2, ...
FROM 소스_테이블
WHERE 조건;
3. 두 방식의 결정적인 차이점 비교
이해를 돕기 위해 주요 항목별로 두 방식을 비교해 보겠습니다.
| 구분 | SELECT INTO | INSERT INTO SELECT |
| 테이블 존재 여부 | 존재하지 않아야 함 (새로 생성) | 이미 존재해야 함 |
| 제약 조건 복사 | 복사되지 않음 (수동 생성 필요) | 기존 테이블의 제약 조건 유지 |
| 복사 대상 | 데이터 타입, 컬럼명, NULL 여부 | 오직 데이터 값 |
| 트랜잭션 로그 | 최소 로깅 가능 (빠른 속도) | 일반적인 로깅 발생 |
| 주 사용 용도 | 백업용 임시 테이블 생성, 마이그레이션 | 주기적인 데이터 수집 및 적재 |
4. 언제 어떤 것을 사용해야 할까? (Best Practices)
SELECT INTO를 사용해야 할 때
- 개발 중 테스트용 테이블 생성: 기존 테이블의 일부분만 떼어내어 테스트해보고 싶을 때 가장 빠릅니다.
- 데이터 백업: 특정 시점의 데이터를 급하게 보관해야 할 때 사용합니다. (예:
SELECT * INTO Backup_Table FROM Original_Table) - 대량 데이터 처리: 수백만 건 이상의 데이터를 아주 빠르게 복사해야 하는 배치 작업 시 유리합니다.
INSERT INTO SELECT를 사용해야 할 때
- 정규화된 운영 테이블 관리: 이미 PK와 인덱스가 꼼꼼하게 설계된 운영 테이블에 데이터를 추가할 때 사용합니다.
- 컬럼 매핑이 필요할 때: 원본 테이블과 대상 테이블의 컬럼 이름이 다르거나, 특정 컬럼에만 값을 넣어야 할 때 적합합니다.
- 데이터 무결성 중요: 중복 데이터 체크 등 제약 조건을 통과해야 하는 데이터 적재 시 필수적입니다.
5. 주의사항 및 꿀팁
IDENTITY 컬럼 처리
SELECT INTO를 사용할 때 소스 테이블에 IDENTITY 컬럼이 있다면 새 테이블에도 그대로 적용됩니다. 하지만 INSERT INTO SELECT를 사용할 때는 대상 테이블의 IDENTITY 속성 때문에 오류가 발생할 수 있습니다. 이럴 때는 SET IDENTITY_INSERT 테이블명 ON 설정을 통해 명시적으로 값을 넣을 수 있습니다.
성능 최적화
대용량 데이터를 INSERT INTO SELECT로 넣을 때 속도가 느리다면, 임시로 인덱스를 제거하거나 TABLOCK 힌트를 사용하여 잠금 경합을 줄이는 방법을 고려해 보세요. 반대로 SELECT INTO 이후에는 반드시 필요한 인덱스를 수동으로 다시 생성해 주어야 성능 저하를 막을 수 있습니다.
결론
MSSQL에서 SELECT INTO와 INSERT INTO SELECT는 상황에 따라 대체 불가능한 각자의 영역을 가지고 있습니다. **”테이블을 새로 만들 것인가, 아니면 기존 그릇에 담을 것인가”**라는 기준만 명확히 세운다면 훨씬 효율적인 데이터베이스 설계와 쿼리 작성이 가능해집니다.
오늘 내용이 여러분의 SQL 실력 향상에 큰 도움이 되었기를 바랍니다. 데이터의 구조와 무결성을 고려하여 최적의 선택을 하시길 응원합니다!
추가로 다른 내용이 궁금하시다면 아래 링크를 확인해주세요!
참고