MySQL을 실무에서 사용할 때 가장 자주 맞닥뜨리는 문제 중 하나는 중복 키(Primary Key 또는 Unique Key) 충돌 시의 처리다.
예를 들어 어떤 데이터는 삽입해야 하지만, 이미 존재하는 경우에는 수정만 하고 싶을 때 어떻게 해야 할까?
바로 그럴 때 사용하는 SQL 문법이 바로 INSERT ... ON DUPLICATE KEY UPDATE이다.
이 문법은 삽입(INSERT)과 동시에 중복 검사 및 조건부 갱신(UPDATE)을 한 번에 처리할 수 있는 아주 강력하고 효율적인 SQL 구문이다.
🔍 INSERT ... ON DUPLICATE KEY UPDATE란?
이 구문은 MySQL에서만 사용 가능한 특수한 INSERT 문법이다.
동작 방식은 아래와 같다.
- 지정한 PRIMARY KEY 또는 UNIQUE KEY가 충돌하지 않으면 INSERT 실행
- 만약 충돌이 발생하면 UPDATE를 대신 수행
즉, 있으면 UPDATE, 없으면 INSERT의 조건문이 한 줄로 해결되는 것이다.
🧾 기본 문법 구조
INSERT INTO 테이블명 (컬럼1, 컬럼2, ...)
VALUES (값1, 값2, ...)
ON DUPLICATE KEY UPDATE
컬럼1 = 새값1,
컬럼2 = 새값2;
여기서 ON DUPLICATE KEY는 충돌이 발생할 키가 반드시 있어야 동작하며, 충돌이 없을 경우에는 일반적인 INSERT로 작동한다.
✅ 기본 예제 – users 테이블에서 중복 시 name 업데이트
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(50)
);
-- 이미 존재하는 id: 1이 있을 경우 name을 업데이트
INSERT INTO users (id, name)
VALUES (1, '김철수')
ON DUPLICATE KEY UPDATE
name = '김철수(수정됨)';
만약 id = 1이 존재하지 않으면 새로 삽입된다.
존재한다면 name 컬럼이 수정되는 방식이다.
🧪 실전 예제 – 중복된 회원 정보 갱신 처리
INSERT INTO users (id, name)
VALUES (2, '이영희')
ON DUPLICATE KEY UPDATE
name = VALUES(name);
VALUES(name)은 삽입하려 했던 값을 그대로 UPDATE에도 사용한다는 뜻이다.
이는 중복 시 기존 값을 덮어쓰되 INSERT 시도했던 값 그대로 재사용하는 실무에서 매우 유용한 패턴이다.
📌 다중 행에서도 사용할 수 있을까?
다중 행 삽입도 가능하지만, 중복된 행이 하나라도 포함되면 해당 행만 UPDATE되고, 나머지는 INSERT된다.
INSERT INTO users (id, name)
VALUES
(3, '박민수'),
(4, '최지은'),
(1, '김철수(변경)')
ON DUPLICATE KEY UPDATE
name = VALUES(name);
이 경우 id = 1만 UPDATE되고, 나머지 id 값은 INSERT된다.
🔄 INSERT IGNORE vs ON DUPLICATE KEY UPDATE 비교
항목 | INSERT IGNORE | ON DUPLICATE KEY UPDATE |
중복 발생 시 | 해당 행 무시 | 해당 행 업데이트 |
에러 발생 여부 | 무시됨 | 없음 |
로그 기록 | 경고만 발생 | UPDATE 처리됨 |
추천 용도 | 단순 중복 회피 | 중복 시 값 갱신 필요할 때 |
⚙️ 활용 팁 – 마지막 업데이트 시간 갱신
로그성 테이블에서 중복된 데이터가 들어올 때, 변경 사항이 없어도 updated_at을 갱신할 수 있다.
INSERT INTO users (id, name, updated_at)
VALUES (5, '홍길동', NOW())
ON DUPLICATE KEY UPDATE
updated_at = NOW();
이 패턴은 웹 사용자 활동 로그나, 최근 접속 시간 저장 등에 활용된다.
🔒 주의사항
- ON DUPLICATE KEY가 동작하려면 반드시 PRIMARY KEY 또는 UNIQUE KEY 제약조건이 있어야 한다.
- REPLACE INTO와 달리 기존 데이터를 삭제하지 않으므로 외래키(FK) 문제 발생 우려가 적다.
- VALUES() 함수는 MySQL 8.0.20부터는 더 이상 권장되지 않고, NEW. 또는 AS 문법이 권장된다.
(아직은 대부분의 환경에서 사용 가능)
💬 활용 예 – 실시간 사용자 상태 갱신
INSERT INTO user_status (user_id, status, last_active)
VALUES (123, 'online', NOW())
ON DUPLICATE KEY UPDATE
status = 'online',
last_active = NOW();
이처럼 실시간 데이터에서 INSERT와 UPDATE를 반복해서 구현할 필요 없이, 이 한 줄로 모든 처리를 끝낼 수 있다.
📎 공식 문서 참고
MySQL INSERT ... ON DUPLICATE KEY UPDATE 공식 문서
https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html
🔖 초강력 해시태그 (SEO 최적화용)
'DB' 카테고리의 다른 글
[MySQL] REPLACE VS INSERT 차이점 완벽 정리 (0) | 2025.06.20 |
---|---|
[MySQL] INSERT + AUTO_INCREMENT 사용법 완벽 가이드 (0) | 2025.06.20 |
[MySQL] INSERT + 트랜잭션(Transaction) 연동 완벽 가이드 (1) | 2025.06.20 |
[MySQL] INSERT + SELECT 사용법 완벽 가이드 (0) | 2025.06.20 |
[MySQL] INSERT IGNORE 사용법 완벽 가이드(데이터 중복 방지) (0) | 2025.06.19 |
[MySQL] INSERT INTO ... SET 사용법 완벽 가이드 (1) | 2025.06.19 |
[MySQL] INSERT 다중 행 삽입 사용법 완벽 가이드 (1) | 2025.06.19 |
[MySQL] INSERT 기본 사용법 완벽 가이드 (0) | 2025.06.19 |