SQL

두 테이블을 비교하여 값 갱신하기, MERGE 사용법

삐삐에스 2025. 12. 11. 00:37

최근에 새로운 개념을 만나지 못해서 블로그를 못쓰고 있었는데 오랜만에 새로운 먹잇감을 발견했다!

오늘은 MERGE 사용법에 대해 알아보려고 한다.

 

오늘 아래와 같은 코드를 보게 되었다.

MERGE INTO TABLE T
USING
	(SELECT 
    	#COL1# COL1,
    	#COL2# COL2,
        #COL3# COL3,
        #COL4# COL4
     FROM DUAL
    ) S
ON (
	T.COL1 = S.COL1
    AND T.COL2 = S.COL2
    AND T.COL3 = S.COL3
   )
WHEN MATCHED THEN
	UPDATE SET
    	T.COL1 = S.COL1,
        T.COL2 = S.COL2,
        T.COL3 = S.COL3,
        T.COL4 = S.COL4
WHEN NOT MATCHED THEN
	INSERT
    	(
        COL1,
        COL2,
        COL3,
        COL4
        )
     VALUES (
     	S.COL1,
        S.COL2,
        S.COL3,
        S.COL4
     )

 

MERGE 키워드는 나에게 생소해서 도대체 어떻게 해석을 해야하는건지 막막했다.

 

우선 MERGE문이란 뭔지 먼저 알아보자.

MERGE문은 테이블에 데이터를 삽입(INSERT)하거나 갱신(UPDATE)하는 작업을 수행할 수 있게 해주는 구문이다.

주로 원본 테이블(Target Table)과 소스 데이터(Source Data)를 비교하여

데이터가 이미 존재하면 갱신(UPDATE)하고,

존재하지 않으면 새로 삽입(INSERT)하는 형식으로 쓰인다.

 

 

이제 MERGE 문의 사용목적은 알았으니 쿼리를 좀 뜯어보자!

 

1. MERGE INTO 뒤에 나오는 TABLE T는 대상 테이블(Target Table)이다.

즉, TABLE T는 '병합 대상'으로 이 테이블의 데이터가 변경된다고 보면 된다.

 

2. USING 뒤에 나오는 SELECT 문은 소스 데이터(Source Data)이다.

대상 테이블에 이 소스 데이터를 적용하게 될 것이다.

 

3. ON 절은 대상 테이블과 소스 데이터의 매칭 조건이다.

이 부분이 MERGE 문의 핵심이다!

쉽게 말해 대상 테이블의 행과 소스 데이터의 행을 연결하는 조인 조건이라고 볼 수 있다.

 

4. WHEN MATCHED THEN ~ 절은 매칭되었을 때 (데이터가 있을 때) 실행되는 구문이다.
ON 절의 결과가 참일 때 THEN 이하 구문이 실행된다.

이 구문은 생략불가하므로 MERGE 문에 반드시 써야한다!

또한 이 구문에는 UPDATE SET이나 DELETE WHERE 문을 사용할 수 있다.

 

5. WHEN NOT MATCHED THEN ~ 절은 매칭되지 않았을 때 (데이터가 없을 때) 실행되는 구문이다.

ON 절의 결과가 거짓일 때 THEN 이하 구문이 실행된다.

이 구문은 WHEN MATCHED THEN 절과 달리 생략 가능하다.

또한 이 구문에는 INSERT INTO 만 사용 가능하다.

 

이 MERGE INTO 구문을 사용하여 쿼리를 하나 짜보자.

동일 테이블에 대해 기준월(BASE_YM)이 당월인 데이터와 기준월이 익월인 데이터를 비교하여
익월 데이터가 있으면 그대로 두고
익월 데이터가 없으면 INSERT하는 형식으로 쿼리를 짜볼 것이다.

 

어떻게 쿼리를 구성하면 좋을까?

먼저 대상 테이블과 소스 데이터는 기준월만 다른 동일 테이블이어야한다.

또 ON 절에는 기준월을 제외한 COL1, COL2가 같아야한다는 조건이 필요하다고 하자.

그럼 아래와 같이 쿼리가 나오게 된다.

MERGE INTO TESTTABLE T
USING
    (
        -- 1. 소스 데이터 (당월 데이터) 조회
        SELECT
            COL1,
            COL2,
            TO_CHAR(ADD_MONTHS(SYSDATE, 1), 'YYYYMM') AS NEXT_BASE_YM 
        FROM
            TESTTABLE
        WHERE
            BASE_YM = TO_CHAR(SYSDATE, 'YYYYMM')
    ) S
ON (
    -- 2. 매칭 조건: 익월 테이블에서 COL1,COL2와 익월 BASE_YM이 일치하는지 확인
    T.COL1 = S.COL1
    AND T.COL2 = S.COL2
    AND T.BASE_YM = S.NEXT_BASE_YM
)
WHEN MATCHED THEN
    -- 3. 매칭됨 (익월 데이터가 이미 존재함): 아무 작업도 하지 않음
    UPDATE SET
        T.COL1 = S.COL1 -- 의미 없는 UPDATE (자기 자신으로 갱신)
    WHERE 1 = 0                  -- **WHERE 1 = 0을 사용하여 실제 갱신 방지**
WHEN NOT MATCHED THEN
    -- 4. 매칭되지 않음 (익월 데이터가 존재하지 않음): INSERT 실행
    INSERT
        (BASE_YM, COL1, COL2)
    VALUES
        (S.NEXT_BASE_YM, S.COL1, S.COL2)
;

 

MERGE 구문을 사용하면 복잡한 요구사항이 와도 위처럼 아주 쉽게 쿼리를 완성할 수 있다!

혹시 이렇게 두 개의 테이블을 비교해서 값을 변형해야할 일이 있다면 MERGE 구문도 고려해보면 좋겠다.

반응형

'SQL' 카테고리의 다른 글

PAD + MOD  (0) 2026.02.03
빈 그릇 테이블, DUAL  (3) 2025.12.16
UNION 사용 시 주의할 점  (0) 2025.11.17