본문 바로가기

개발/SQL

[SQL] Oracle - MERGE (+ MyBatis에서 동적으로 사용)

 

< MERGE >

 

- 조건을 비교해서 테이블에 해당 조건에 맞는 데이터가 없으면 INSERT, 있으면 UPDATE 실행

- 해당 조건을 넣어서 한 문장으로 경우에 따른 처리가 가능

 

[ 표현법 ]

MERGE INTO 테이블명

USING (UPDATE나 INSERT 될 값)

      ON (조건)

 WHEN MATCHED THEN

       UPDATE

               SET 컬럼1 = 값1, 컬럼2 = 값2, ...

        WHERE update 조건

*      DELETE

        WHERE delete 조건

 WHEN NOT MATCHED THEN

        INSERT (컬럼1, 컬럼2, ...) VALUES (값1, 값2, ...)

       WHERE insert 조건

 

* DELETE 구문 추가 가능

 

 

 

- 사용 예시 1 -

유저에게 정지일자를 부여하는 테이블에

해당 유저가 이미 입력된 적이 있는 경우 UPDATE, 없는경우 INSERT를 부여하기 위해 사용함

<update id="stopMember" parameterType="_int">
    merge into penalty
    using dual
    on (mem_no = #{memNo})
    when matched then
        UPDATE
           SET
               END_DATE = SYSDATE + 7
         WHERE 
               MEM_NO = #{memNo}
    when not matched then
        INSERT (mem_no, end_date)
        VALUES
               (
               #{memNo}
               ,SYSDATE + 7
               )
</update>

- 단일 테이블내에서는 USING에 dual을 넣어 사용

- ON () 안에 일치하는지 확인할 조건을 작성

  : 전달한 유저 번호가 매치하는 행이 있는지 확인

- WHEN MATCHED THEN에 매칭되면 수행할 UPDATE문을 작성

  : 정지일을 현재 날짜의 7일 이후로 수정

- WHEN NOT MATCHED THEN에 매칭되는 행이 없을 경우 실행할 INSERT문을 작성

  : 해당 컬럼에 맞게 유저 번호와 정지일을 입력

 

 

- 사용 예시 2 - 

스킬을 입력하는 테이블에 스킬 목록(list)을 가지고가서 해당하는 스킬이 없는 경우 INSERT 하기 위해 사용함

<update id="updateSkill" parameterType="list">
    MERGE 
     INTO CODE_SKILL C
    USING 
          (
          <foreach collection="list" item="item" index="index" separator="UNION ALL" open="(" close=")">
            select #{item} as skill_name from dual
          </foreach>
          ) S
       ON (C.SKILL_NAME = S.SKILL_NAME)
     WHEN NOT MATCHED THEN
      	INSERT 
      	VALUES(CODE_SKILL_SEQ.NEXTVAL, S.SKILL_NAME)
</update>

- USING내에 UNION ALL로 묶인 SELECT문(foreach로 생성)을 넣어서 조회되는 값들을 조건에 따라 처리

- CODE_SKILL 테이블에 "C" 별칭, USING에 쓰인 조회값에 "S" 별칭 - 들고간 값은 S에 존재

- WHEN MATCHED THEN UPDATE 구문을 생략하고, 일치하지 않을 때 INSERT문만을 수행하도록 함

 

* 그렇지만 이렇게 수행했더니 존재하는 기술에도 구문을 실행하게 되면서 code_skill_seq가 발동되어버림...

  시퀀스 값이 계속 증가하는 꼴...