- 1 1. Introduction
- 2 2. What Is ON DUPLICATE KEY UPDATE?
- 3 3. Basic Usage Examples
- 4 4. 고급 사용법
- 5 5. 함정과 모범 사례
- 6 6. 다른 데이터베이스의 유사 기능
- 7 7. 결론
- 8 8. FAQ
- 8.1 Q1: MySQL의 어떤 버전에서 ON DUPLICATE KEY UPDATE 를 지원하나요?
- 8.2 Q2: 기본 키가 없을 때 ON DUPLICATE KEY UPDATE 를 사용할 수 있나요?
- 8.3 Q3: ON DUPLICATE KEY UPDATE 와 REPLACE 의 차이점은 무엇인가요?
- 8.4 Q4: ON DUPLICATE KEY UPDATE 사용 시 성능을 어떻게 최적화할 수 있나요?
- 8.5 Q5: 중복 감지 조건을 변경할 수 있나요?
- 8.6 Q6: “Duplicate entry” 오류가 발생하는 원인과 해결 방법은?
- 8.7 Q7: 트리거가 ON DUPLICATE KEY UPDATE 에 영향을 미치나요?
- 8.8 Q8: 다른 데이터베이스에서도 동일한 쿼리를 사용할 수 있나요?
- 8.9 Summary
1. Introduction
데이터베이스를 다룰 때 흔히 겪는 문제 중 하나는 중복 데이터 처리입니다. 예를 들어 고객 정보를 관리하는 시스템에서 새 고객을 등록할 때, 해당 데이터가 이미 존재하는지 확인하고 필요하면 업데이트해야 합니다. 이 과정을 수동으로 관리하면 오류가 발생하거나 처리 지연이 생길 수 있습니다.
이때 MySQL의 ON DUPLICATE KEY UPDATE 구문이 유용합니다. 이 기능을 사용하면 중복 데이터가 감지될 때 자동으로 적절한 동작을 수행할 수 있습니다. 그 결과 데이터 관리가 보다 효율적으로 이루어지고 개발자의 작업 부담이 줄어듭니다.
본 문서에서는 ON DUPLICATE KEY UPDATE의 기본 구문과 사용 예시, 고급 기법, 그리고 유의해야 할 핵심 포인트를 설명합니다. 이를 통해 초급부터 중급까지의 개발자들이 실제 프로젝트에서 이 기능을 효과적으로 활용할 수 있게 됩니다.
2. What Is ON DUPLICATE KEY UPDATE?
MySQL에서 ON DUPLICATE KEY UPDATE는 INSERT 문이 기본 키 또는 고유 키 제약을 위반할 경우 기존 데이터를 자동으로 업데이트해 주는 편리한 절입니다. 이를 통해 하나의 쿼리만으로 데이터 삽입과 업데이트를 효율적으로 처리할 수 있습니다.
Basic Concept
보통 INSERT 문으로 데이터를 삽입할 때, 중복된 기본 키나 고유 키가 있으면 오류가 발생합니다. 하지만 ON DUPLICATE KEY UPDATE를 사용하면 다음과 같은 동작을 수행할 수 있습니다:
- 삽입하려는 데이터가 새 데이터라면 INSERT 작업이 정상적으로 실행됩니다.
- 삽입하려는 데이터가 기존 데이터와 충돌하면 지정한 컬럼이 업데이트됩니다.
이렇게 하면 오류를 피하면서 효율적인 데이터 조작이 가능합니다.
Basic Syntax
ON DUPLICATE KEY UPDATE의 기본 구문은 다음과 같습니다:
INSERT INTO table_name (column1, column2, column3)
VALUES (value1, value2, value3)
ON DUPLICATE KEY UPDATE column1 = value1, column2 = value2;
table_name: 대상 테이블 이름.column1, column2, column3: 삽입할 컬럼 이름들.value1, value2, value3: 삽입할 값들.ON DUPLICATE KEY UPDATE: 중복 키가 감지될 때 수행할 업데이트 동작을 지정합니다.
Requirements
이 절이 정상 작동하려면 테이블에 다음 제약 중 하나 이상이 존재해야 합니다:
- PRIMARY KEY : 고유한 값을 보유하는 컬럼.
- UNIQUE KEY : 중복 값을 허용하지 않는 컬럼.
위 제약이 하나도 없으면 ON DUPLICATE KEY UPDATE는 동작하지 않습니다.
Example
간단한 예시로, 사용자 정보를 관리하는 테이블에 데이터를 삽입하거나 업데이트하는 경우를 살펴보겠습니다.
Table Definition
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(50),
email VARCHAR(100) UNIQUE
);
Using INSERT
다음 쿼리는 사용자 ID 또는 이메일 주소가 이미 존재하는 경우를 처리합니다:
INSERT INTO users (id, name, email)
VALUES (1, 'Taro', 'taro@example.com')
ON DUPLICATE KEY UPDATE name = 'Taro', email = 'taro@example.com';
- ID가 1인 사용자가 이미 존재한다면
name과email값이 업데이트됩니다. - 존재하지 않으면 새로운 레코드가 삽입됩니다.
3. Basic Usage Examples
이 섹션에서는 ON DUPLICATE KEY UPDATE의 기본 사용 예시를 소개합니다. 단일 레코드와 다중 레코드 작업을 각각 설명합니다.
Handling a Single Record
중복 데이터가 존재할 경우 삽입과 동시에 업데이트가 이루어지는 단일 레코드 예시를 살펴보겠습니다.
Table Definition
CREATE TABLE products (
id INT PRIMARY KEY,
name VARCHAR(50),
stock INT
);
Basic INSERT Statement
다음 쿼리는 ID가 1인 제품 데이터를 삽입합니다. 이미 존재한다면 stock 값이 업데이트됩니다.
INSERT INTO products (id, name, stock)
VALUES (1, 'Product A', 100)
ON DUPLICATE KEY UPDATE stock = 100;
How It Works
- 제품 ID 1이 존재하지 않으면 새로운 레코드가 삽입됩니다.
- 제품 ID 1이 이미 존재하면
stock컬럼이100으로 업데이트됩니다.
다중 레코드 처리
다음으로, 여러 레코드를 한 번에 처리하는 방법을 살펴보겠습니다.
다중 값의 대량 삽입
다음 쿼리는 여러 제품 레코드를 한 번에 삽입합니다:
INSERT INTO products (id, name, stock)
VALUES
(1, 'Product A', 100),
(2, 'Product B', 200),
(3, 'Product C', 300)
ON DUPLICATE KEY UPDATE stock = VALUES(stock);
작동 방식
VALUES(stock)은 각 레코드에 삽입되는 값(100,200,300)을 의미합니다.- 제품 ID가 이미 존재하면, 삽입된 값을 기준으로 재고가 업데이트됩니다.
- 존재하지 않으면 새 레코드가 삽입됩니다.
고급: 동적 값 업데이트
기존 데이터를 기반으로 값을 동적으로 업데이트할 수도 있습니다. 예를 들어, 기존 재고에 추가하는 경우:
INSERT INTO products (id, name, stock)
VALUES (1, 'Product A', 50)
ON DUPLICATE KEY UPDATE stock = stock + VALUES(stock);
작동 방식
- 제품 ID 1이 이미 존재하면, 현재
stock값에50이 추가됩니다. - 존재하지 않으면
stock이50으로 설정된 새 레코드가 삽입됩니다.
요약
- 단일 레코드뿐만 아니라 다중 레코드도 한 번에 효율적으로 처리할 수 있습니다.
VALUES()를 사용하면 삽입된 데이터를 기반으로 컬럼을 유연하게 업데이트할 수 있습니다.
4. 고급 사용법
ON DUPLICATE KEY UPDATE를 사용하면 기본 삽입/업데이트 작업을 넘어 보다 유연한 데이터 처리를 구현할 수 있습니다. 이 섹션에서는 조건부 업데이트와 트랜잭션과의 결합과 같은 고급 사용 패턴을 설명합니다.
조건부 업데이트
ON DUPLICATE KEY UPDATE를 사용하면 CASE 표현식이나 IF 함수를 이용해 컬럼을 조건부로 업데이트할 수 있습니다. 이를 통해 상황에 따라 보다 유연한 업데이트 로직을 구현할 수 있습니다.
예시: 재고가 임계값 이하일 때만 업데이트
다음 예시는 현재 재고가 특정 수치 이하일 때만 재고 값을 업데이트합니다.
INSERT INTO products (id, name, stock)
VALUES (1, 'Product A', 100)
ON DUPLICATE KEY UPDATE stock = CASE
WHEN stock < 50 THEN VALUES(stock)
ELSE stock
END;
작동 방식
- 제품 ID 1이 존재하고 현재 재고가 50보다 작으면, 새로운 값(
100)으로 업데이트됩니다. - 재고가 50 이상이면 업데이트되지 않고 기존 값이 유지됩니다.
동적 업데이트 사용
삽입된 데이터를 기반으로 동적 계산을 수행하고 값을 업데이트할 수도 있습니다.
예시: 누적 값 업데이트
다음 예시는 삽입된 재고 값을 기존 재고에 더합니다.
INSERT INTO products (id, name, stock)
VALUES (2, 'Product B', 50)
ON DUPLICATE KEY UPDATE stock = stock + VALUES(stock);
작동 방식
- 제품 ID 2가 이미 존재하면, 기존
stock값에50이 추가됩니다. - 존재하지 않으면 새 레코드가 삽입됩니다.
트랜잭션과 결합
트랜잭션 내에서 여러 INSERT 문(및 기타 데이터 작업)을 실행하면 데이터 일관성을 유지하면서 복잡한 작업을 수행할 수 있습니다.
예시: 트랜잭션을 이용한 배치 처리
다음 예시는 여러 레코드를 배치로 처리하고 오류가 발생하면 롤백합니다.
START TRANSACTION;
INSERT INTO products (id, name, stock)
VALUES
(1, 'Product A', 100),
(2, 'Product B', 200)
ON DUPLICATE KEY UPDATE stock = VALUES(stock);
INSERT INTO products (id, name, stock)
VALUES
(3, 'Product C', 300)
ON DUPLICATE KEY UPDATE stock = stock + VALUES(stock);
COMMIT;
작동 방식
START TRANSACTION과COMMIT사이에서 여러 쿼리가 실행됩니다.- 어떤 쿼리라도 실패하면 트랜잭션이 롤백되고 데이터베이스에 변경 사항이 적용되지 않습니다.
고급 사용을 위한 실용 시나리오
시나리오 1: 전자상거래 사이트의 재고 관리
제품이 구매될 때 재고 수량을 감소시켜야 할 수 있습니다.
INSERT INTO products (id, name, stock)
VALUES (4, 'Product D', 100)
ON DUPLICATE KEY UPDATE stock = stock - 1;
시나리오 2: 사용자 포인트 시스템
기존 사용자에게 포인트를 추가할 때:
INSERT INTO users (id, name, points)
VALUES (1, 'Taro', 50)
ON DUPLICATE KEY UPDATE points = points + VALUES(points);
요약
CASE표현식과 동적 업데이트를 사용하여 복잡한 조건부 로직을 구현할 수 있습니다.- 트랜잭션을 결합하면 데이터 일관성을 유지하면서 안전한 작업을 수행할 수 있습니다.
- 이 기능을 실제 시나리오에 적용하면 더 효율적인 데이터 관리가 가능합니다.

5. 함정과 모범 사례
ON DUPLICATE KEY UPDATE를 사용할 때 잘못된 사용은 예상치 못한 동작이나 성능 저하를 초래할 수 있습니다. 이 섹션에서는 이를 효과적으로 사용하기 위한 주요 함정과 모범 사례를 강조합니다.
주요 함정
1. AUTO_INCREMENT와의 상호 작용
- 문제 기본 키가
AUTO_INCREMENT를 사용하는 경우, 중복이 발생하더라도 자동 증가 값이 증가할 수 있습니다. 이는 MySQL이 INSERT를 시도할 때 새로운 ID를 예약하기 때문입니다. - 해결책 INSERT 충돌 시 ID 낭비를 피하려면 고유 키(단순 AUTO_INCREMENT가 아닌)를 사용하고, 필요 시
LAST_INSERT_ID()를 사용하여 최신 ID를 검색하세요.INSERT INTO products (id, name, stock) VALUES (NULL, 'Product E', 50) ON DUPLICATE KEY UPDATE stock = stock + VALUES(stock);
2. 데드락 위험
- 문제 여러 스레드가 동일한 테이블에서 ON DUPLICATE KEY UPDATE를 동시에 실행하면 데드락이 발생할 수 있습니다.
- 해결책
- 쿼리 실행 순서를 표준화하세요.
- 필요 시 테이블 잠금을 사용하세요(하지만 성능 영향에 주의).
- 데드락 발생 시 재시도 로직을 구현하세요.
3. 적절한 인덱스 설계
- 문제 기본 키나 고유 키가 없으면 ON DUPLICATE KEY UPDATE가 작동하지 않습니다. 또한, 잘못된 인덱싱은 성능을 심각하게 저하시킬 수 있습니다.
- 해결책 항상 기본 키나 고유 키를 정의하고, 자주 검색되거나 업데이트되는 열에 적절한 인덱스를 추가하세요.
모범 사례
1. 사전 데이터 확인
- 삽입 전에
SELECT문을 사용하여 데이터가 존재하는지 확인하고 의도하지 않은 업데이트를 방지하세요.SELECT id FROM products WHERE id = 1;
2. 트랜잭션 사용
- 여러 INSERT/UPDATE 작업을 그룹화하기 위해 트랜잭션을 사용하세요. 이는 일관성을 안전하게 유지하는 데 도움이 됩니다.
START TRANSACTION; INSERT INTO products (id, name, stock) VALUES (1, 'Product A', 100) ON DUPLICATE KEY UPDATE stock = stock + 50; COMMIT;
3. 업데이트 열 최소화
- 업데이트할 열을 제한하여 성능을 향상시키고 불필요한 변경을 피하세요.
INSERT INTO products (id, name, stock) VALUES (1, 'Product A', 100) ON DUPLICATE KEY UPDATE stock = VALUES(stock);
4. 오류 처리 구현
- 데드락이나 실패한 삽입에 대비하여 재시도나 롤백 로직을 포함한 오류 처리를 구현하세요.
요약
- 함정 : AUTO_INCREMENT 증가, 데드락, 잘못된 인덱스 설계에 주의하세요.
- 모범 사례 : 트랜잭션과 오류 처리를 사용하여 데이터를 안전하고 효율적으로 처리하세요.
6. 다른 데이터베이스의 유사 기능
MySQL의 ON DUPLICATE KEY UPDATE는 효율적인 데이터 처리를 가능하게 하는 강력한 기능입니다. 그러나 이는 MySQL에 특화된 기능입니다. 다른 데이터베이스 시스템은 유사한 기능을 제공하지만, 각각 다른 특성을 가집니다. 이 섹션에서는 PostgreSQL과 SQLite의 유사 기능을 비교합니다.
PostgreSQL: ON CONFLICT DO UPDATE
PostgreSQL에서 해당 기능은 ON CONFLICT DO UPDATE입니다. 이 절은 충돌 발생 시 수행할 작업을 지정하여 중복 데이터를 유연하게 처리하는 방법을 제공합니다.
기본 구문
INSERT INTO table_name (column1, column2)
VALUES (value1, value2)
ON CONFLICT (column1) DO UPDATE
SET column2 = value2;
ON CONFLICT (column1): 충돌 대상(예: 기본 키 또는 고유 키)을 지정합니다.DO UPDATE: 충돌이 발생할 때 실행할 업데이트 작업을 정의합니다.
예시
제품 테이블에서 제품 ID가 이미 존재하면 재고를 업데이트합니다:
INSERT INTO products (id, name, stock)
VALUES (1, 'Product A', 100)
ON CONFLICT (id) DO UPDATE
SET stock = EXCLUDED.stock;
EXCLUDED.stock: 삽입하려고 시도한 값에 대한 참조입니다.
주요 특징
- MySQL과의 차이점 PostgreSQL은 충돌 조건을 명시적으로 정의할 수 있어 여러 고유 제약 조건이 있는 테이블과 작업할 때 더 유연합니다.
- 장점 고급 조건부 로직을 지원하며 업데이트할 열에 대한 세밀한 제어를 제공합니다.
SQLite: INSERT OR REPLACE / INSERT OR IGNORE
SQLite는 INSERT OR REPLACE와 INSERT OR IGNORE를 제공하며, 이는 MySQL 및 PostgreSQL 구문과 약간 다릅니다.
INSERT OR REPLACE
INSERT OR REPLACE는 중복이 감지되면 기존 행을 삭제하고 새 행을 삽입합니다.
기본 구문
INSERT OR REPLACE INTO table_name (column1, column2)
VALUES (value1, value2);
예시
제품 ID가 이미 존재하면 기존 레코드를 삭제하고 새 레코드를 삽입합니다:
INSERT OR REPLACE INTO products (id, name, stock)
VALUES (1, 'Product A', 100);
주요 특징
- 동작 차이점 MySQL이나 PostgreSQL과 달리 SQLite는 새 레코드를 삽입하기 전에 기존 레코드를 제거합니다.
- 주의사항 기존 레코드가 삭제되기 때문에 삭제 트리거가 실행될 수 있습니다. 트리거가 정의되어 있다면 주의하세요.
INSERT OR IGNORE
INSERT OR IGNORE는 중복이 존재하면 오류를 발생시키지 않고 조용히 작업을 건너뜁니다.
비교 테이블
| Database | Syntax | Characteristics |
|---|---|---|
| MySQL | ON DUPLICATE KEY UPDATE | Updates specific columns when duplicates occur. Simple and efficient. |
| PostgreSQL | ON CONFLICT DO UPDATE | Supports advanced conditional logic and high flexibility. |
| SQLite | INSERT OR REPLACE / IGNORE | REPLACE deletes then inserts. IGNORE skips errors. |
요약
- MySQL의 ON DUPLICATE KEY UPDATE는 삽입-또는-업데이트 로직을 처리하는 데 간단하고 효율적입니다.
- PostgreSQL의 ON CONFLICT DO UPDATE는 더 많은 유연성과 고급 제어를 제공합니다.
- SQLite의 INSERT OR REPLACE는 삽입 전에 기존 데이터를 삭제하며, 이는 삭제 작업을 트리거할 수 있습니다.
7. 결론
이 기사에서 우리는 MySQL의 ON DUPLICATE KEY UPDATE를 기본 구문부터 고급 사용 사례, 중요한 고려 사항, 그리고 다른 데이터베이스 시스템과의 비교까지 탐구했습니다. 이 기능을 제대로 이해하고 사용함으로써 데이터베이스 작업을 더 효율적으로 만들고 애플리케이션 성능과 신뢰성을 향상시킬 수 있습니다.
ON DUPLICATE KEY UPDATE의 장점
- 효율적인 데이터 관리
- 삽입 및 업데이트 작업을 단일 쿼리로 처리할 수 있어 처리 과정이 간결하고 빠릅니다.
- 간소화된 중복 처리
- 중복 데이터에 대한 동작을 명확히 정의하고 오류 위험을 줄일 수 있습니다.
- 높은 유연성
- 더 고급 시나리오를 위한 동적 업데이트와 조건부 로직을 지원합니다.
효과적인 사용 시나리오
- 재고 관리 시스템
- 제품 재고 수준을 동적으로 업데이트합니다.
- 사용자 관리 시스템
- 사용자 정보를 추가하거나 업데이트합니다.
- 포인트 관리 시스템
- 사용자 보상 포인트를 추가하거나 업데이트합니다.
이러한 시나리오에서 ON DUPLICATE KEY UPDATE를 사용하면 코드 복잡성을 줄이고 유지보수성을 향상시킬 수 있습니다.
중요한 고려 사항 검토
- AUTO_INCREMENT 고려 사항
- 기본 키가
AUTO_INCREMENT를 사용하는 경우 중복이 발생하더라도 ID가 증가할 수 있음을 유의하세요.
- 데드락 방지
- 쿼리 실행 순서와 트랜잭션 구조를 적절히 설계하세요.
- 인덱스 설계의 중요성
- 오류를 피하고 성능을 향상시키기 위해 기본 키와 고유 키를 적절히 구성하세요.
비교 하이라이트
- PostgreSQL의 ON CONFLICT DO UPDATE는 유연한 충돌 대상을 지원합니다.
- SQLite의 INSERT OR REPLACE는 삽입 전에 삭제하며, 이는 트리거에 영향을 줄 수 있습니다.
최종 권장 사항
- 간단한 삽입/업데이트 작업에는 ON DUPLICATE KEY UPDATE 를 적극적으로 사용하십시오.
- 대규모 작업이나 복잡한 로직의 경우, 트랜잭션 및 사전 검사를 결합하여 안전성을 높이세요.
ON DUPLICATE KEY UPDATE 를 적절히 사용하면 개발 효율성과 애플리케이션 신뢰성을 모두 향상시킬 수 있습니다. 이 글의 개념을 여러분의 프로젝트에 적용해 보세요.
8. FAQ
이 문서에서는 MySQL의 ON DUPLICATE KEY UPDATE 에 관한 다양한 측면을 다루었습니다. 아래 섹션에서는 자주 묻는 질문들을 모아 실용적인 인사이트를 추가로 제공하고자 합니다.
Q1: MySQL의 어떤 버전에서 ON DUPLICATE KEY UPDATE 를 지원하나요?
- A1: MySQL 4.1.0 이상에서 사용할 수 있습니다. 다만 버전마다 동작이 다를 수 있으니, 사용 중인 버전의 공식 문서를 반드시 확인하십시오.
Q2: 기본 키가 없을 때 ON DUPLICATE KEY UPDATE 를 사용할 수 있나요?
- A2: 아니요. 기본 키 또는 최소 하나의 고유 키가 정의된 테이블에서만 동작합니다.
Q3: ON DUPLICATE KEY UPDATE 와 REPLACE 의 차이점은 무엇인가요?
- A3:
- ON DUPLICATE KEY UPDATE 는 중복이 감지될 경우 지정된 컬럼을 업데이트합니다.
- REPLACE 는 기존 레코드를 삭제한 뒤 새 레코드를 삽입하므로, 삭제 동작이 발생하고 데이터 일관성에 영향을 줄 수 있습니다.
Q4: ON DUPLICATE KEY UPDATE 사용 시 성능을 어떻게 최적화할 수 있나요?
- A4:
- 적절한 인덱스 설계 : 기본 키와 고유 키를 올바르게 정의합니다.
- 업데이트 컬럼 최소화 : 필요한 컬럼만 업데이트합니다.
- 트랜잭션 사용 : 배치 작업으로 데이터베이스 오버헤드를 줄입니다.
Q5: 중복 감지 조건을 변경할 수 있나요?
- A5: 조건을 변경하려면 기본 키 또는 고유 키 정의를 수정해야 합니다. ON DUPLICATE KEY UPDATE 자체의 동작은 변경할 수 없습니다.
Q6: “Duplicate entry” 오류가 발생하는 원인과 해결 방법은?
- A6:
- 원인 : 기본 키 또는 고유 키 제약을 위반하는 데이터를 삽입하려 할 때 발생합니다.
해결 : wp:list {“ordered”:true} /wp:list
- 테이블 스키마를 확인하고 중복을 일으키는 컬럼을 파악합니다.
SELECT문을 사용해 삽입 전에 기존 데이터를 확인합니다.- 충돌을 처리하도록 ON DUPLICATE KEY UPDATE 를 적절히 구성합니다.
Q7: 트리거가 ON DUPLICATE KEY UPDATE 에 영향을 미치나요?
- A7: 예.
INSERT와UPDATE트리거가 ON DUPLICATE KEY UPDATE 사용 시 모두 실행될 수 있습니다. 트리거 로직을 그에 맞게 설계하십시오.
Q8: 다른 데이터베이스에서도 동일한 쿼리를 사용할 수 있나요?
- A8: 다른 데이터베이스도 유사한 기능을 제공하지만, 문법과 동작이 다릅니다. 예시:
- PostgreSQL :
ON CONFLICT DO UPDATE - SQLite :
INSERT OR REPLACE
Summary
이 FAQ에서는 ON DUPLICATE KEY UPDATE 에 대한 일반적인 질문들을 다루었습니다. 오류 원인 파악 및 성능 최적화 전략을 이해하는 것은 특히 운영 환경에서 매우 중요합니다. 문제가 발생하면 이 가이드를 참고해 문제를 해결하십시오.
ON DUPLICATE KEY UPDATE 를 마스터하면 효율적이고 신뢰할 수 있는 데이터베이스 작업을 구현할 수 있습니다.


