UPSERT는 "삽입하되 이미 존재하면 업데이트"를 의미합니다. PostgreSQL은 이를 **INSERT ... ON CONFLICT**로 구현합니다 — 행을 삽입하되, 고유 제약조건을 위반하게 되면 대신 기존 행을 업데이트(또는 아무것도 하지 않음)합니다. 흔한 "삽입-또는-업데이트" 필요를 원자적으로 처리합니다.
UPSERT가 해결하는 문제
행을 삽입하고 싶지만 (고유 키로) 이미 존재할 수 있는 경우:
❌ 일반 INSERT는 존재 시 고유 위반 오류로 실패
❌ 확인-후-삽입 (SELECT 후 INSERT 또는 UPDATE)은 RACE CONDITION 존재
(확인과 삽입 사이에 다른 transaction이 삽입할 수 있음)
→ ON CONFLICT는 단일 문장에서 원자적으로 처리 (race condition 없음)
ON CONFLICT DO UPDATE — 삽입 또는 업데이트
users (email, name, login_count)
(, , )
CONFLICT (email)
DO
name EXCLUDED.name,
login_count users.login_count ;
