DB

MSSQL MERGE문 <-> Postgresql WITH문

DevHam94 2024. 1. 16. 10:45

두 구문은 비슷하다. 

해당하는 자료가없으면 INSERT문을 실행하고 있으면 UPDATE문을 사용하는데 

구문이 조금 다르다. 

 

# mssql 

MERGE INTO table_a AS a
USING (
select
	 #{A} as B
	,#{B} as B
)
AS b
   ON (a.A = b.A)
   and (a.B = b.B)
 WHEN MATCHED THEN
   UPDATE 
   	SET  a.C = #{C}
   		,a.D = CURRENT_TIMESTAMP
   		,a.E  = #{E}
 WHEN NOT MATCHED THEN
   INSERT(
   		 A
   		,F
   )VALUES(
   		 #{A}
   		,#{F}
   );

mssql은 이런식으로 mybatis에서 가져온 데이터를 USING문에서 변수에 넣어준다. 그리고 이 b라고 alias를 선언해주는데 ON절에서 이 조건에 맞는 자료가있으면 조건에 맞는 데이터에 UPDATE문을 실행시켜주고 WHEN NOT MATCHED THEN 즉 일치하지 않을때는 INSERT문을 실행시켜준다.

 

 

# postgresql 

WITH tbl_with AS (
    SELECT #{A} AS A, #{B} AS B, to_char(#{C}::timestamp, 'YYYY-MM-DD') AS C
),
tbl_updated AS (
    UPDATE target_table a
    SET
        A = b.A,
        B = b.B,
        C = b.C::timestamp
    FROM tbl_with b
    WHERE
        a.A = b.A
        AND a.B = b.B
    RETURNING a.A, a.B, a.C
),
tbl_inserted AS (
    INSERT INTO target_table (
        A,
        B,
        C
    )
    SELECT
        a.A,
        a.B,
        a.C::timestamp
    FROM tbl_with a
    WHERE NOT EXISTS (
        SELECT *
        FROM tbl_updated b
        WHERE a.A = b.A
          AND a.B = b.B
    )
    returning A, B
)
SELECT SUM(x.cnt) AS cnt
FROM (
    SELECT COUNT(*) AS cnt FROM tbl_updated
    UNION ALL
    SELECT COUNT(*) AS cnt FROM tbl_inserted
) x;

postgresql의 WITH문도 MERGE문하고 비슷한데 이런식으로 tbl_with문에 가져온 데이터들을 변수에 담아주고 tbl_updated 내에서 WHERE문에 일치하면 UPDATE문을 실행시켜주고 없으면 tbl_updated문에 데이터가 없으므로 아패서 WHERE NOT EXISTS에 아무것도 안뜨게 되어 INSERT문이 실행된다. 참고로 아래 SELECT절에서 CNT절을 꼭 적어줘야 정상적으로 실행이된다.