MERGE INTO 문 중 DATA를 변수로 받고 싶습니다. 0 2 6,233

by 강서꽃미남 [PL/SQL] MERGE PLSQL 프로시저 패키지 [2012.03.05 01:23:44]




안녕하십니까.
패키지 만드는 중 하나 질문 드립니다.
커서 를 선언하지 않고 MERGE INTO 쿼리문을 사용해 그대로 데이터를 때려박았습니다.

오류가 없으면 JOB로그를 남기고 있으면 ERR로그를 남기는 그런 패키지 인데,
제가 알고 싶은 부분은
MERGE INTO OG_ODS_ORDER_SUMMARY_LJJ  T -- OG_ODS_ORDER_SUMMARY_LJJ 에 데이터 적재
   USING (SELECT A.YEAR
   , A.MONTH
   , SHOP_CODE
   , SHOP_NAME
   , A.TOT_AMT
   , A.PLAN_AMT
   , ABS((A.TOT_AMT - A.PLAN_AMT)) AS DIFF_AMT
   , DECODE(A.PLAN_AMT,0,0,((A.TOT_AMT / A.PLAN_AMT) * 100)) AS DIFF_RATE
   , CREATER
   , CREAT_TIME
    FROM (SELECT A.YEAR
   , A.MONTH
   , A.SHOP AS SHOP_CODE
   , A.NAME AS SHOP_NAME
   , A.TOT_AMT
   , NVL( (SELECT SUM(PL_AMT) FROM OG_ODS_PLAN_BY_MAEJANG_LJJ WHERE YEAR(+) = A.YEAR AND MONTH(+) = A.MONTH AND SHOP(+) = A.SHOP ), 0 ) AS PLAN_AMT
   , CREATER
   , CREAT_TIME
    FROM (SELECT /*+ INDEX( A OG_ODS_ORDER_AGGREGATION_PK ) */ A.YEAR
   , A.MONTH
   , A.SHOP
   , (SELECT NAME FROM OG_MST_SHOP_LJJ WHERE SHOP = A.SHOP ) AS NAME
   , SUM(A.TOT_AMT) AS TOT_AMT
   , 'LJJ' AS CREATER
   , SYSDATE AS CREAT_TIME
    FROM OG_ODS_ORDER_AGGREGATION_LJJ A
   WHERE BASE_DATE BETWEEN IN_FROM_DATE AND IN_TO_DATE
   GROUP BY A.YEAR, A.MONTH , A.SHOP
) A
)A
   ) F  
  ON ( F.YEAR = T.YEAR AND F.MONTH = T.MONTH AND F.SHOP_CODE = T.SHOP_CODE )
   WHEN MATCHED THEN -- 값이 존재하면 UPDATE
UPDATE SET T.SHOP_NAME = F.SHOP_NAME
  , T.TOT_AMT =  F.TOT_AMT
  , T.PLAN_AMT = F.PLAN_AMT
  , T.DIFF_AMT = F.DIFF_AMT 
  , T.DIFF_RATE = F.DIFF_RATE
  , T.CREATER = F.CREATER
  , T.CREAT_TIME = F.CREAT_TIME
    WHEN NOT MATCHED THEN -- 값이 존재하지 않으면 INSERT
   INSERT ( T.YEAR 
  , T.MONTH
  , T.SHOP_CODE
  , T.SHOP_NAME
  , T.TOT_AMT
  , T.PLAN_AMT
  , T.DIFF_AMT
  , T.DIFF_RATE
  , T.CREATER
  , T.CREAT_TIME
  )
   VALUES ( F.YEAR
  , F.MONTH
  , F.SHOP_CODE
  , F.SHOP_NAME
  , F.TOT_AMT
  , F.PLAN_AMT
  , F.DIFF_AMT
  , F.DIFF_RATE
  , F.CREATER
  , F.CREAT_TIME
  );
  s_YEAR := F.YEAR -- YEAR
  s_MONTH := F.MONTH --MONTH
  DBMS_OUTPUT.PUT_LINE(v_YEAR||v_MONTH);
  d_ETIME := SYSDATE; -- 작업종료시간 저장
  EXCEPTION
  WHEN OTHERS THEN
    n_ERCODE := SQLCODE; -- 에러코드 변수에 저장
    v_ERMSG  := SQLERRM; -- 에러메시지 변수에 저장
    DBMS_OUTPUT.PUT_LINE('JOB_LOG 에러코드:' || n_ERCODE || '  에러메시지:' || v_ERMSG || '  성공실패여부:' || v_YN);
   END;
    IF TO_CHAR(n_ERCODE)  = '0'  OR
   TO_CHAR(n_ERCODE) IS NULL THEN
   v_YN := 'Y';    -- 에러발생 X
    ELSE
   v_YN := 'N';
   ROLLBACK;
   GOTO JUMP; -- 에러발생 (RATE 적재 하지않고 바로 JOB과 ERR_JOB에 기록
    END IF;
  
   SAVEPOINT MERGE_RATE;

밑 줄 친 부분처럼 저렇게 적용은 되지 않더군요, JOB로그에 일일히 찍고 싶으나, 한번에 데이터가 들어가서 일일히는 안될 것 같고 마지막 ROW의 YEAR, MONTH 값이라도 찍고 싶은데, 두줄을 제외하고 패키지를실행하면 위에서 정의한 변수 초기화 부분 YEAR := NULL 로 들어가서 NOTNULL 제약조건에 걸려 에러가 발생합니다.

커서를 사용하지 않고, MERGE INTO 을 사용했을 경우, DATA를 변수로 받아서 OUT파라미터로 내보낼수 있을까요.
답변 부탁드립니다.
감사합니다.

-- 참고하시라고 총 패키지 쿼리 도 첨부해뒀습니다.
by 강서꽃미남 [2012.03.06 08:36:35]

커서문을 새로 추가해서 돌려서 해결했습니다.


by 웬쑤 [2014.02.05 14:35:22]

귀한 경험 공유해 주셔서 감사합니다~

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