oracle merge 다시 질문 드립니다. 0 4 489

by 개발자 [SQL Query] [2020.11.26 01:09:15]


테이블명 : yeardata

pk : year, seq

초기 테이블 데이터 없는 상태임.

 

case 1.

변수값

year seq data
2020 1 200
2021 2 300
2022 3 400

처리 결과

year seq status data
2020 1 C 200
2021 2 C 300
2022 3 C 400

설명

1. DB에 없는 변수값을 Insert(status : C)

 

case 2.(case 1 결과값이 DB 데이터)

변수값 

year seq data
2020 1 200
2021 2 250

처리 결과

year seq status data
2020 1 U 200
2021 2 U 250
2022 3 D 400

설명 :

1. 2020, 2021 -> 변수값과 DB 데이터간 pk(year, seq)  조건 데이터가 있는 경우 status, data 값 update(C -> U)

2. 2022 -> DB 데이터에는 있으나 변수값에 없는 경우 status 값 update(C -> D)

 

case 3.(case 2 결과값이 DB 데이터)

변수값

year seq data
2020 1 100
2021 2 250
2022 4 500
2023 5 550

처리 결과

year seq status data
2020 1 U 100
2021 2 U 250
2022 3 D 400
2022 4 C 500
2023 5 C 550

설명

1. seq 1, 2, 3은 case 2와 같은 경우

2. seq 4, 5 번은 DB에 없는 신규 데이터라 Insert(case 1과 같은 경우)

 

하나의 merge 문으로 위 경우를 모두 처리할 수 있는지 문의 드립니다.

 

by 마농 [2020.11.26 08:22:17]
-- 변수값을 임시테이블에 입력 한 뒤에 다음과 같이 처리하세요.
MERGE INTO yeardata a
USING
(
SELECT NVL(a.year, b.year) year
     , NVL(a.seq , b.seq ) seq
     , NVL(b.data, a.data) data
     , DECODE(null, a.seq, 'C', b.seq, 'D', 'U') status
  FROM yeardata a
  FULL OUTER JOIN input_t b
    ON a.year = b.year
   AND a.seq  = b.seq
) b
ON (a.year = b.year
AND a.seq  = b.seq)
WHEN MATCHED THEN
    UPDATE
       SET status = b.status
         , data   = b.data
WHEN NOT MATCHED THEN
    INSERT
    VALUES (b.year, b.seq, b.status, b.data)
;

 


by 개발자 [2020.11.26 09:07:57]

답변 감사 드립니다.

이것 때문에 임시 테이블을 만들수는 없어서요.


by 마농 [2020.11.26 09:24:38]
-- 글쎄요? 변수 자체로는 안될 것 같습니다.
-- 어떻게 해서든 테이블 형태로 처리가 되어야 할텐데요. --
MERGE INTO yeardata a
USING
(
WITH input_t(year, seq, data) AS
(
          SELECT '2020', 1, 200 FROM dual
UNION ALL SELECT '2021', 2, 300 FROM dual
UNION ALL SELECT '2022', 3, 400 FROM dual
)
SELECT NVL(a.year, b.year) year
     , NVL(a.seq , b.seq ) seq
     , NVL(b.data, a.data) data
     , DECODE(null, a.seq, 'C', b.seq, 'D', 'U') status
  FROM yeardata a
  FULL OUTER JOIN input_t b
    ON a.year = b.year
   AND a.seq  = b.seq
) b
ON (a.year = b.year
AND a.seq  = b.seq)
WHEN MATCHED THEN
    UPDATE
       SET status = b.status
         , data   = b.data
WHEN NOT MATCHED THEN
    INSERT
    VALUES (b.year, b.seq, b.status, b.data)
;

 


by 마농 [2020.11.26 11:26:35]
-- 변수로 루프 돌려가면서 1건씩 처리한다고 하면
-- 처리 전 전체 데이터를 D 로 업데이트 한 후에
-- 루프 처리로 한건씩 머지하면 될 듯 합니다.

-- 1. 전체 D 로 갱신
UPDATE yeardata SET status = 'D';
-- 2. LOOP 문 안에서 1건씩 Merge --
MERGE INTO yeardata a
USING dual
ON (a.year = :v_year
AND a.seq  = :v_seq)
WHEN MATCHED THEN
    UPDATE
       SET status = 'U'
         , data   = :v_data
WHEN NOT MATCHED THEN
    INSERT
    VALUES (:v_year, :v_seq, 'C', :v_data)
;

 

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입