데이터를 삽입할 때 이미 존재하는 고유 키가 존재하여 에러가 발생하는 상황을 처리하는 방법이 필요할 때가 많아요. 단순히 삽입을 시도하고 실패할 경우에만 업데이트를 수행하는 로직을 애플리케이션 단에서 구현할 수도 있지만, 데이터베이스 레벨에서 제공하는 Upsert 구문을 활용하면 훨씬 효율적이고 원자적인 처리가 가능하거든요.

MySQL에서는 INSERT ... ON DUPLICATE KEY UPDATE 구문을 사용하여 이를 해결할 수 있어요. 이 구문은 Insert 문을 실행하다가 Primary Key나 Unique 인덱스 중 하나라도 충돌이 발생할 경우, 해당 행을 Update 문으로 전환하여 실행하는 방식이에요. 특히 업데이트할 값을 지정할 때 VALUES(컬럼명) 함수를 사용하면 원본 쿼리에 포함된 값을 그대로 재사용할 수 있어 편리하더라고요. 이 방식은 데이터베이스 엔진이 인덱스 충돌을 직접 감지하여 처리하기 때문에 고부하 상황에서도 안정적으로 작동해요.

INSERT INTO users (id, name, email)
VALUES (1, 'John', 'john@example.com')
ON DUPLICATE KEY UPDATE name = VALUES(name), email = VALUES(email);

PostgreSQL에서는 INSERT ... ON CONFLICT 구문을 통해 동일한 기능을 구현해요. PostgreSQL의 방식은 좀 더 명시적이며, 어떤 제약 조건이나 인덱스를 기반으로 충돌을 판별할지 명시적으로 기술하는 구조를 가지고 있어요. 예를 들어 ON CONFLICT (target_column) DO UPDATE SET ... 형식을 사용하여 특정 컬럼의 충돌을 감지하고 업데이트를 수행하거나, 충돌이 발생했을 때 아무런 작업도 하지 않는 DO NOTHING 옵션을 사용할 수도 있어요. 이러한 세부 옵션들은 복잡한 비즈니스 로직을 데이터베이스 쿼리 수준에서 깔끔하게 처리할 수 있게 도와줘요.

INSERT INTO users (id, name, email)
VALUES (1, 'John', 'john@example.com')
ON CONFLICT (id) DO UPDATE SET 
    name = EXCLUDED.name,
    email = EXCLUDED.email;

결과적으로 두 데이터베이스 모두 Upsert 기능을 지원하지만 문법과 세부 제어 방식에서 차이를 보이고 있어요. MySQL은 인덱스 충돌 시 자동으로 업데이트를 수행하는 범용적인 접근 방식을 취하고 있고, PostgreSQL은 충돌 조건과 후속 동작을 명시적으로 기술하는 방식을 채택하고 있거든요. 따라서 서비스의 요구사항과 사용하는 데이터베이스 엔진의 특성을 고려하여 적절한 구문을 선택하면 데이터 무결성을 유지하면서도 효율적인 데이터 삽입 로직을 구성할 수 있어요.

+ Recent posts