본문 바로가기

Backend/Database

[Oracle] MERGE INTO 사용법

728x90

테이블에 데이터가 이미 있으면 UPDATE 를 실행하고, 없을 경우 값을 INSERT 해줘야 하는 경우에  MERGE INTO 문을 통해 한 쿼리로 간단하게 작성할 수 있다. 

 

오라클 9i 버전 이상부터 사용 가능 (but 10g이상 사용 추천)

 

아래와 같이 사용한다.

MERGE INTO "테이블 명"
USING "테이블 or 뷰 or 서브쿼리" 
ON (
      " 조건절1" 
      AND  " 조건절2 " 
      ...
)	-- 값이 있는지 확인
WHEN MATCHED THEN 	--있으면 
	UPDATE SET
     [COLUMN1] = [VALUE1],          
     [COLUMN2] = [VALUE2],
WHEN NOT MATCHED THEN 	--없으면
	INSERT (COLUMN1, COLUMN2, ...) 
    VALUES (VALUE1, VALUE2, ...)

단일 테이블로 사용할때,  dual 사용

* dual : 오라클 자체에서 제공되는 테이블, 오직 한행, 한컬럼을 담고 있는 dummy 테이블 

MERGE 
 INTO emp a
USING dual
   ON (a.empno = 7788)
 WHEN MATCHED THEN
      UPDATE
         SET a.deptno = 20
 WHEN NOT MATCHED THEN
      INSERT (a.empno, a.ename, a.deptno)
      VALUES (7788, 'SCOTT', 20);

 

USING 절에 테이블 대신 dual을 사용하면 된다. ON 조건절이 일치하면 UPDATE, 불일치하면 INSERT를 하는 쿼리이다.

emp 라는 테이블에 empno값이 7788이면, update문 실행하고 아니면 insert문 실행한다.

 

실제로 개발할때 아래와 같이 사용했다.

MERGE INTO "부서테이블" USING DUAL ON (
	LOC_GOV_CD = ?
    AND GOV_OFFICD_CD = ? 
    ...
)
WHEN MATCHED THEN 
UPDATE SET
  LOC_GOV_CD = ? 
  AND GOV_OFFICD_CD = ? 
  ...
  CHG_DT = TO_CHAR(SYSDATE, 'YYYYMMDDHH24MMSS'),
  ...
WHEN NOT MATCHED THEN
INSERT (
  LOC_GOV_CD,
  ...
) VALUES (
  ?
  ...
)

 

- USING ~ ON ( "조건절" )  -> 조건절에 사용한 컬럼은 UPDATE 불가능함. 따라서 PK로 비교 

- DELETE 문도 사용 가능 (오라클 10g 이상 가능)  따라서 오라클 10g이상일 경우만 MERGE 문 사용하는게 좋음. 

* 단점?

- 성능 문제 

처음 작업속도는 빠르지만, 시간이 지날수록 작업속도가 느려지므로 인덱스 전략을 잘 수립해서 사용 필요 

대용량 처리 할 경우 CPU 점유율 높아져 부하발생 -> 중소규모작업 (10만건 이하) 일 경우 유용함.

 

- DB 변경될 경우가 있을까? 

변경되는 DB에 MERGE문 없으면 소스 변경 공수 많이듬. 그래서 범용적인 쿼리문 사용하는게 좋음 (그럴 경우가 많을까?) 

 

- 쿼리 리펙토링 문제가 있나? 

나중에 쿼리 리펙토링 할때 어려울 것 같음. SELECT이후 분기처리 하는게 리펙토링 면에서 유리할 것이다. 

 

상황에 따라 맞게 쓰면 될 것 같다. 


Ref.

 

MERGE

Prerequisites You must have the INSERT and UPDATE object privileges on the target table and the READ or SELECT object privilege on the source table. To specify the DELETE clause of the merge_update_clause, you must also have the DELETE object privilege on

docs.oracle.com

 

728x90