[Oracle] Insert와 Update를 동시에 처리할 때

AhnMin·2024년 7월 23일

ERP 개발을 진행하다 보면 INSERT와 UPDATE를 동시에 처리해야 되는 경우가 빈번하다.

보통 비즈니스 로직에서는 REST API를 설계할 때 이를 각 요청에 맞게 처리를 하지만 코드가 길어지는건 유지보수 측면에서 그 만큼 꾸준히 관리돼야 하는 부분도 많아진다는 단점이 있다.

1. 데이터가 존재하는지 확인
2. 데이터가 존재하면 UPDATE
3. 데이터가 없으면 INSERT

위와 같이 3가지 경우를 모두 선언하는건 너무 번거러운 부분이 있다.

  • Oracle MERGE INTO

이 경우 Oracle에 도움을 받으면 코드를 획기적으로 줄일 수 있는데 바로 MERGE INTO를 사용하는 것이다.

MERGE INTO [TABLE / VIEW] 		// update 또는 insert할 테이블 혹은 뷰
     USING [TABLE / VIEW / DUAL] 	// 비교할 대상 테이블 혹은 뷰 (위 테이블과 동일할 경우 DUAL을 사용)
        ON [조건] 			// UPDATE 와 INSERT 처리할 조건문 (조건이 일치하면 UPDATE / 불일치 시 INSERT)
      WHEN MATCHED THEN 
                 UPDATE 
                    SET
                       [COLUMN1] = [VALUE1],
                       [COLUMN2] = [VALUE2],
                             ...
                             
            (DELETE [TABLE] WHERE [COLUMN 1] = [VALUE 1] AND ...) // UPDATE 뿐만 아니라 DELETE 구문도 사용 가능
      
      WHEN NOT MATCHED THEN
                     INSERT (COLUMN1, COLUMN2, ...)
         	     VALUES (VALUE1, VALUE2, ...)

MERGE INTO 예 기본적인 구조는 위와 같고 주의할 점은 동시에 여러 트랜잭션이 실행될 경우 데드락이 발생할 수 있지만 어지간한 경우가 아니면 거의 없긴하다.

  • MERGE INTO 활용
MERGE INTO T_I_FAMILY tgt
-- 대상 테이블 T_I_FAMILY을 업데이트하거나 삽입할 대상 테이블로 설정
USING (
    SELECT EMP_CD, SEQ, JUMIN_NO, NM, RELATION_CD, ABILITY_CD
    FROM T_I_FAMILY_MIS
    WHERE CNF_YN = 'N'
      AND EMP_CD = #{empCd}
) src
-- 소스 테이블 T_I_FAMILY_MIS에서 조건에 맞는 데이터를 선택
-- CNF_YN이 'N'이고 EMP_CD가 특정 값인 데이터를 선택
ON (tgt.EMP_CD = src.EMP_CD AND tgt.SEQ = src.SEQ)
-- 대상 테이블과 소스 테이블을 EMP_CD와 SEQ 컬럼을 기준으로 매칭
WHEN MATCHED THEN
    -- 매칭되는 경우 업데이트 수행
    UPDATE SET
        tgt.JUMIN_NO = src.JUMIN_NO,
        tgt.NM = src.NM,
        tgt.RELATION_CD = src.RELATION_CD,
        tgt.ABILITY_CD = src.ABILITY_CD
    -- 소스 테이블의 JUMIN_NO, NM, RELATION_CD, ABILITY_CD 값을 대상으로 업데이트
WHEN NOT MATCHED THEN
    -- 매칭되지 않는 경우 삽입 수행
    INSERT (EMP_CD, SEQ, JUMIN_NO, NM, RELATION_CD, ABILITY_CD)
    VALUES (src.EMP_CD, src.SEQ, src.JUMIN_NO, src.NM, src.RELATION_CD, src.ABILITY_CD)
    -- 소스 테이블의 EMP_CD, SEQ, JUMIN_NO, NM, RELATION_CD, ABILITY_CD 값을 대상으로 삽입

위 예시를 적용하여 가족정보 중 가족사항이 추가되거나 수정되는 경우를 구현하였다.

해당 쿼리는 데이터가 수정되거나 추가된 경우 전,후 데이터를 비교하여 로직을 다르게 처리할 수 있는 장점이 있다.

예를 들어 WHEN MATCHED절에서 기존 데이터를 업데이트할 때 변경된 데이터를 쉽게 확인할 수 있으며, 그게 아닐 경우WHEN NOT MATCHED절에서 새로운 가족 정보를 삽입할 수 있다.

느낀점

서비스 호출이 많아지면 운영 서버에 데이터 처리량이 많아질 수 있고 그 과정에서 사용자는 서비스 속도나 처리 과정에 답답함을 느낄 수 있다.

위 과정을 통해 운영 서버에 부하를 나눌 수 있었고(DB 서버가 나뉘어져 있을 때)

항상 느끼는 거지만 개발은 쿼리를 잘 활용하면 로직 처리에 있어서 많이 수월함을 느끼는 경우가 많은 것 같다.

profile
INFP 낙서장

2개의 댓글

comment-user-thumbnail
2024년 7월 23일

글 잘 읽었습니다~ 내용이 참 좋네요 :)

답글 달기
comment-user-thumbnail
2024년 7월 23일

유익한 정보 감사합니다 도움이 많이 됐네요 ^^

답글 달기