📄 10편. MERGE 문으로 UPSERT 처리하기
Oracle에서 MERGE 문은 INSERT와 UPDATE를 동시에 처리할 수 있는 강력한 SQL 문입니다.
특히 ETL, 배치 처리, 대량 데이터 동기화에서 널리 사용됩니다.
이번 글에서는 MERGE 문 기본 구조와 실전 예제를 통해 UPSERT를 구현하는 방법을 정리합니다.
📚 예제 테이블: 회원 정보 동기화
CREATE TABLE MEMBER (
ID NUMBER PRIMARY KEY,
NAME VARCHAR2(50),
EMAIL VARCHAR2(100)
);
-- 기존 데이터
INSERT INTO MEMBER VALUES (1, 'Kim', 'kim@example.com');
INSERT INTO MEMBER VALUES (2, 'Lee', 'lee@example.com');
COMMIT;
-- 신규/수정 대상 데이터
CREATE TABLE MEMBER_STAGE (
ID NUMBER,
NAME VARCHAR2(50),
EMAIL VARCHAR2(100)
);
INSERT INTO MEMBER_STAGE VALUES (1, 'Kim', 'new_kim@example.com'); -- UPDATE 대상
INSERT INTO MEMBER_STAGE VALUES (3, 'Park', 'park@example.com'); -- INSERT 대상
COMMIT;
🔁 MERGE 기본 구조
MERGE INTO MEMBER T
USING MEMBER_STAGE S
ON (T.ID = S.ID)
WHEN MATCHED THEN
UPDATE SET T.EMAIL = S.EMAIL
WHEN NOT MATCHED THEN
INSERT (ID, NAME, EMAIL)
VALUES (S.ID, S.NAME, S.EMAIL);
MERGE INTO
: 대상 테이블USING
: 비교할 소스 테이블ON()
: 매칭 조건 (기준 PK 또는 유니크 키)- WHEN MATCHED: UPDATE 수행
- WHEN NOT MATCHED: INSERT 수행
MERGE INTO USER_INFO A
USING (
SELECT
#{chainCd} AS CHAIN_CD,
#{userId} AS USER_ID,
#{userNm} AS USER_NM,
#{email} AS EMAIL
FROM DUAL
) B
ON (A.CHAIN_CD = B.CHAIN_CD AND A.USER_ID = B.USER_ID)
WHEN MATCHED THEN
UPDATE SET
A.USER_NM = B.USER_NM,
A.EMAIL = B.EMAIL
WHEN NOT MATCHED THEN
INSERT (CHAIN_CD, USER_ID, USER_NM, EMAIL)
VALUES (B.CHAIN_CD, B.USER_ID, B.USER_NM, B.EMAIL);
신규로 넣을지 기존값을 수정할지 들어온 값은 성격에 따라 FROM DUAL에서 새로 생성할수도 있지만,
기존에 A과 관련된 모든 테이블(C,D,E)과 조인해서 기존테이블들에 반드시 있는 경우에 A에 신규로 넣거나 A에 업데이트를 결정해야하는 경우에는 해당 테이블에 조건이 있는지 WHERE 조건을 걸어서 조회해야 하는 경우도 있다.
⚠ 필터링 조건을 정확하게 걸지 않으면 의도하지 않게 데이터가 다건이 한 번에 insert될 수 있으니 주의해야한다.
📌 MERGE 결과 확인
SELECT * FROM MEMBER;
ID | NAME | |
---|---|---|
1 | Kim | new_kim@example.com |
2 | Lee | lee@example.com |
3 | Park | park@example.com |
⚠ MERGE 문 사용 시 주의사항
- ON 조건이 모호하거나 중복되면 ORA-30926: unable to get a stable set of rows 오류 발생
- UPSERT 대상이 많을 경우 MERGE보다 별도 INSERT/UPDATE 분리 전략이 성능상 유리할 수 있음
- MERGE는 DML이므로 COMMIT 필요
🧠 실무 팁
- MERGE는 대량 데이터 비교/동기화에 적합 (예: 일 단위 고객 정보 갱신)
- 소스 테이블을
WITH
절이나인라인 뷰
로 작성해도 무방 - 조건부 UPDATE (예: 값이 달라질 때만 UPDATE) 도 가능
WHEN MATCHED THEN
UPDATE SET T.EMAIL = S.EMAIL
WHERE T.EMAIL != S.EMAIL
📝 마무리
이번 글에서는 Oracle의 MERGE 문을 사용한 UPSERT 처리 방법을 실습 예제로 설명했습니다.
다음 글부터는 고급 SQL과 성능 최적화 영역으로 들어가며, WITH절과 재귀 쿼리를 다룰 예정입니다.
'database > oracle' 카테고리의 다른 글
🌳 12편. 동적 SQL과 EXECUTE IMMEDIATE (0) | 2025.05.06 |
---|---|
🌳 11편. WITH절과 재귀 쿼리 (WITH RECURSIVE) (0) | 2025.05.06 |
📄 9편. Pivot / Unpivot으로 행열 변환하기 (0) | 2025.05.06 |
📄 8편. 계층 쿼리 완전 정복 (CONNECT BY) (0) | 2025.05.06 |
📄 7편. 조인(Join)과 서브쿼리(Subquery) 정복 (0) | 2025.05.06 |
댓글