
MySQL을 활용하다 보면 한 테이블에서 데이터를 조회(SELECT)한 후
다른 테이블에 삽입(INSERT)해야 하는 상황이 자주 발생한다.
예를 들어, 주문 데이터를 백업 테이블에 저장하거나,
조건에 맞는 유저만 특정 테이블에 복사하고 싶을 때가 있다.
이럴 때 사용하는 문법이 바로 INSERT INTO ... SELECT이다.
중간 결과 없이 직접 SELECT 결과를 삽입하는 이 기술은,
MySQL 실무에서 매우 자주 사용되는 고급 기능 중 하나다.
🔍 INSERT INTO ... SELECT 문법이란?
INSERT INTO ... SELECT는 말 그대로
SELECT 문을 통해 조회한 결과를 INSERT 문으로 삽입하는 방식이다.
일반적인 INSERT VALUES와 달리,
데이터를 직접 지정하는 대신 SELECT 쿼리로 값을 가져온다.
기본 문법
INSERT INTO 대상_테이블 (컬럼1, 컬럼2, ...)
SELECT 컬럼1, 컬럼2, ...
FROM 원본_테이블
WHERE 조건;
조회한 데이터가 그대로 대상 테이블에 삽입되며,
중간에 임시 테이블을 만들 필요도 없다.
✅ 기본 예제 – users 테이블에서 특정 회원만 백업하기
-- 기존 회원 테이블
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(50),
age INT
);
-- 백업용 테이블
CREATE TABLE users_backup (
id INT,
name VARCHAR(50),
age INT
);
-- age가 30 이상인 회원만 백업
INSERT INTO users_backup (id, name, age)
SELECT id, name, age
FROM users
WHERE age >= 30;
이 예제에서는 users 테이블에서 조건에 맞는 데이터를 골라
users_backup 테이블에 한 번에 삽입하고 있다.
🧪 실전 예제 – 최근 접속 회원만 활동 로그에 추가하기
-- 접속 로그용 테이블
CREATE TABLE active_logs (
user_id INT,
last_login DATETIME
);
-- 최근 7일 이내 접속한 회원만 기록
INSERT INTO active_logs (user_id, last_login)
SELECT id, NOW()
FROM users
WHERE last_login >= DATE_SUB(NOW(), INTERVAL 7 DAY);
SELECT 결과 중에서 특정 조건을 만족하는 행만 추출해서
활동 로그 테이블에 삽입하는 방식이다.
이 방식은 SELECT + FOR문 처리보다 훨씬 빠르고 효율적이다.
🔁 컬럼 수와 순서가 정확히 일치해야 함
- SELECT 결과의 컬럼 개수와 순서가, INSERT 대상 컬럼과 정확히 일치해야 한다.
- 컬럼명이 달라도 상관 없지만, 데이터 타입과 순서는 맞아야 한다.
-- 잘못된 예: 컬럼 개수가 다름
INSERT INTO users_backup (id, name)
SELECT id, name, age FROM users;
-- 에러 발생
🔄 자동 증가(PK) 컬럼이 있는 경우 주의사항
- 자동 증가 컬럼(auto_increment)은 명시하지 않으면 자동 채번됨
- 명시해서 넣는 경우, 중복키 충돌에 주의해야 함
-- id 값을 생략한 경우, 자동 증가
INSERT INTO users_backup (name, age)
SELECT name, age FROM users WHERE id > 100;
💬 활용 예 – 제품 가격 변경 이력 저장하기
-- 가격 변경 로그 테이블
CREATE TABLE product_price_log (
product_id INT,
old_price INT,
change_time DATETIME
);
-- 가격이 10000원 이상인 제품만 이력 저장
INSERT INTO product_price_log (product_id, old_price, change_time)
SELECT id, price, NOW()
FROM products
WHERE price >= 10000;
이런 방식은 데이터 변경 전 이력을 남기기 위해 자주 활용된다.
⚠️ 주의사항
- SELECT 문에 JOIN을 사용해도 문제없지만, 결과 컬럼 수만 정확히 맞추면 된다.
- 조건 없이 전체 데이터를 복사할 경우, 실수로 데이터 중복이 생길 수 있으니 WHERE 절은 필수로 넣는 습관을 들이는 것이 좋다.
- INSERT ... SELECT는 성능적으로 매우 효율적이지만, 대상 테이블이 잠길 수 있으므로 대량 데이터 삽입 시 주의해야 한다.
✅ INSERT SELECT + 트랜잭션 조합
START TRANSACTION;
INSERT INTO archive_users (id, name, age)
SELECT id, name, age FROM users WHERE deleted = 1;
DELETE FROM users WHERE deleted = 1;
COMMIT;
위와 같이 INSERT + SELECT + DELETE를 묶어
백업 후 삭제하는 패턴도 매우 실무에서 자주 쓰인다.
📌 요약
- INSERT INTO ... SELECT는 조회된 데이터를 다른 테이블에 삽입할 수 있는 효율적인 방법이다.
- 백업, 로그, 데이터 이관, 조건부 복사 등 다양한 업무에 활용할 수 있다.
- 컬럼 수와 순서가 일치해야 하며, JOIN, 서브쿼리, WHERE 절 등과도 함께 사용 가능하다.
- 트랜잭션과 결합하면 데이터 무결성과 안정성 확보에도 유리하다.
📎 공식 문서 참고
MySQL INSERT SELECT 공식 문서
https://dev.mysql.com/doc/refman/8.0/en/insert-select.html
'DB' 카테고리의 다른 글
| [MySQL] 대량 INSERT 성능 최적화 방법 완벽 정리 (1) | 2025.06.20 |
|---|---|
| [MySQL] REPLACE VS INSERT 차이점 완벽 정리 (0) | 2025.06.20 |
| [MySQL] INSERT + AUTO_INCREMENT 사용법 완벽 가이드 (0) | 2025.06.20 |
| [MySQL] INSERT + 트랜잭션(Transaction) 연동 완벽 가이드 (2) | 2025.06.20 |
| [MySQL] 있으면 UPDATE, 없으면 INSERT (오라클의 MERGE INTO) (2) | 2025.06.19 |
| [MySQL] INSERT IGNORE 사용법 완벽 가이드(데이터 중복 방지) (0) | 2025.06.19 |
| [MySQL] INSERT INTO ... SET 사용법 완벽 가이드 (1) | 2025.06.19 |
| [MySQL] INSERT 다중 행 삽입 사용법 완벽 가이드 (1) | 2025.06.19 |