Atomic Habits

merge into , update set 본문

IT/SQL

merge into , update set

체계성 2021. 12. 16. 22:12

WHEN MATCHED THEN - UPDATE,DELETE 만 가능

WHEN NOT MATCHED THEN - INSERT 만 가능

 

UPDATE T2 TTT SET nm = (select nm from T1 where C1 = TTT.C1);

 

 

MERGE INTO target_t a
USING
(
SELECT NVL(b.pk, a.pk) pk
     , NVL(b.c1, a.c1) c1
     , NVL(b.c2, a.c2) c2
     , NVL2(b.pk, 'M', 'D') flag
  FORM target_t a
  FULL OUTER JOIN source_t b
    ON a.pk = b.pk
) b
ON a.pk = b.pk
WHEN MATCHED THEN
  UPDATE c1 = b.c1, c2 = b.c2      -- b(O) - a(O)
  DELETE WHERE b.flag = 'D'        -- b(X) - a(O)
WHEN NOT MATCHED THEN
  INSERT VALUES(b.pk, b.c1, b.c2)  -- b(O) - a(X)
;
 
-- 기존에 미포함된 데이터 제거
select * from t1 where c1 not in (select c1 from t2);
delete from t1 where c1 not in (select c1 from t2);
select * from t1;
rollback;

select * from t1 a, t2 b where a.c1 = b.c1;

select * from t1
MINUS
select * from t2;

-- 기존 테이블과 새 테이블에서 코드는 일치하나, 이름이 다를 경우 update set 수행
UPDATE T1 NEW SET NEW.C2 = (SELECT RUN.C2 FROM T2 RUN WHERE RUN.C1 = NEW.C1)
WHERE EXISTS (SELECT 2 FROM T2 RUN WHERE RUN.C1 = NEW.C1);


MERGE INTO T1 NEW
USING T2 RUN
ON (NEW.C1 = RUN.C1)
WHEN MATCHED THEN
    UPDATE SET NEW.C2 = RUN.C2
;
select * from t1;
ROLLBACK;

 

 

 

CREATE TABLE TB1 ( NAME VARCHAR2(20), AGE NUMBER(3) ); -- 테이블 TB1 생성

INSERT INTO TB1(NAME, AGE) VALUES('이영희', 35);
INSERT INTO TB1(NAME, AGE) VALUES('박영수', 40);
INSERT INTO TB1(NAME, AGE) VALUES('엄영수', 40); -- TB1에 값 삽입

MERGE INTO TB1 A       -- 사용할 테이블
USING DUAL             -- 비교할 테이블(테이블 하나만 사용할 경우 DUAL 사용)
ON (A.NAME = '김철수') -- 비교 조건(조건에 사용한 컬럼은 UPDATE 불가능)
	WHEN MATCHED THEN  -- 조건에 맞을 시
		UPDATE SET A.AGE = 50 WHERE A.NAME = '김철수' -- TB1의 해당하는 줄의 AGE를 50으로 변경
		DELETE WHERE A.NAME = '김철수' -- UPDATE 후 DELETE 문(생략 가능)
	WHEN NOT MATCHED THEN -- 조건에 맞지 않을 시
		INSERT (NAME, AGE) VALUES('김철수', 30); -- INSERT문 수행

 

MERGE INTO TTR_TABLE T
USING (
        SELECT A.R_ID     AS R_ID
               ,A.R_DT    AS R_DT
               ,A.R_NM    AS R_NM
               ,A.R_IN_J  AS R_IN_J
               ,A.R_TN    AS R_TN
               ,B.R_BN    AS R_BN
          FROM TTA_TABLE A
               ,TTB_TABLE B
         WHERE 1=1
           AND A.R_ID = B.R_ID
           AND A.R_DT BETWEEN '20200101' AND '20201231'
         GROUP BY A.R_ID
               ,A.R_DT
       ) S
    ON (T.P_ID = S.R_ID
   AND T.P_DT = S.R_DT)
  WHEN MATCHED THEN
UPDATE SET
       T.P_NM = S.R_RM
       ,T.P_IN_J = S.R_IN_J
       ,T.P_TN = S.R_TN
       ,T.P_BN = S.R_BN
  WHEN NOT MATCHED THEN
INSERT ( P_ID
        ,P_DT
        ,P_NM
        ,P_IN_J
        ,P_TN
        ,P_BN)
       VALUES (S.R_ID
               ,S.R_DT
               ,S.R_NM
               ,S.R_IN_J
               ,S.R_TN
               ,S.R_BN)
;
 

2. 어떤 값을 UPDATE또는 INSERT할지 SELECT문 부터 살퍄 보도록 하죠. 어떤 값들을 넣어줄지 얼마나 되는지 확인하는 작업도 되고 하나씩 쪼개서 보아야 실수를 줄일 수 있죠. USING의 괄호 안에 있는 부분 입니다.

        SELECT A.R_ID     AS R_ID
               ,A.R_DT    AS R_DT
               ,A.R_NM    AS R_NM
               ,A.R_IN_J  AS R_IN_J
               ,A.R_TN    AS R_TN
               ,B.R_BN    AS R_BN
          FROM TTA_TABLE A
               ,TTB_TABLE B
         WHERE 1=1
           AND A.R_ID = B.R_ID
           AND A.R_DT BETWEEN '20200101' AND '20201231'
         GROUP BY A.R_ID
               ,A.R_DT
  
where조건에 1=1은 모든 조건이 일치한지 확인하는 그문이고, and조건에 R_ID가 A와 B모두에 있고 날짜는 20200101~20201231까지로 합니다. 이 조건에 해당하는 데이터들이 있는지 조회를 해 보고 조건이 맞는지도 확인합니다. 
 

3. 조회된 내역이 맞다면 ON부분에 있는 조건들이 있으면 (WHEN MATCHED THEN) UPDATE를 하고 없으면(WHEN NOT MATCHED THEN) INSERT를 합니다. 

 ※만약 둘 중에 하나의 조건만 원한다면 하나의 조건절을 삭제하고 진행하면 됩니다. UPDATE만 원하면 WHEN NOT MATCHED THEN 부분부터 아래의 내용을 삭제하면 되고, 반대의.경우는 WHEN MATCHED THEN 부분부터 WHEN NOT MATCHED THEN 부분 전 까지 삭제를 하면 됩니다. 

 

/*업데이트만 할 경우*/
MERGE INTO TTR_TABLE T
USING (
        SELECT A.R_ID     AS R_ID
               ,A.R_DT    AS R_DT
               ,A.R_NM    AS R_NM
               ,A.R_IN_J  AS R_IN_J
               ,A.R_TN    AS R_TN
               ,B.R_BN    AS R_BN
          FROM TTA_TABLE A
               ,TTB_TABLE B
         WHERE 1=1
           AND A.R_ID = B.R_ID
           AND A.R_DT BETWEEN '20200101' AND '20201231'
         GROUP BY A.R_ID
               ,A.R_DT
       ) S
    ON (T.P_ID = S.R_ID
   AND T.P_DT = S.R_DT)
  WHEN MATCHED THEN
UPDATE SET
       T.P_NM = S.R_RM
       ,T.P_IN_J = S.R_IN_J
       ,T.P_TN = S.R_TN
       ,T.P_BN = S.R_BN
;

/*인서트만 할 경우*/
MERGE INTO TTR_TABLE T
USING (
        SELECT A.R_ID     AS R_ID
               ,A.R_DT    AS R_DT
               ,A.R_NM    AS R_NM
               ,A.R_IN_J  AS R_IN_J
               ,A.R_TN    AS R_TN
               ,B.R_BN    AS R_BN
          FROM TTA_TABLE A
               ,TTB_TABLE B
         WHERE 1=1
           AND A.R_ID = B.R_ID
           AND A.R_DT BETWEEN '20200101' AND '20201231'
         GROUP BY A.R_ID
               ,A.R_DT
       ) S
    ON (T.P_ID = S.R_ID
   AND T.P_DT = S.R_DT)
  WHEN NOT MATCHED THEN
INSERT ( P_ID
        ,P_DT
        ,P_NM
        ,P_IN_J
        ,P_TN
        ,P_BN)
       VALUES (S.R_ID
               ,S.R_DT
               ,S.R_NM
               ,S.R_IN_J
               ,S.R_TN
               ,S.R_BN)
;

 

출처 : https://yoocodec.tistory.com/entry/oracleMERGE-INTO-%EB%A1%9C-%EC%97%AC%EB%9F%ACROW-%ED%95%9C%EA%BA%BC%EB%B2%88%EC%97%90-UPDATE-%EB%B0%8F-INSERT

 

 

Comments