DB

[MySQL] 있으면 UPDATE, 없으면 INSERT (오라클의 MERGE INTO)

인생아 2025. 6. 19. 16:46
반응형

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 최적화용)

less
복사편집
#MySQL #ONDUPLICATEKEYUPDATE #MySQL중복업데이트 #MySQL조건부삽입 #INSERTUPDATE #MySQL중복처리 #SQL중복키 #MySQL실전예제 #MySQLINSERT #MySQL트랜잭션
반응형