BAYPASS, MERGE 질문!! 0 8 4,119

by 람짱 [Oracle Tuning] [2011.04.29 11:27:54]



안녕하세요.. 궁굼한것이 있습니다!!

이번에 10G R2 -> 11G R2로 DBMS 업글을 위해 이것저것 테스트 중에..

10G에서는 잘 돌아가는데 11G에서는 돌아가지 않는 업데이트문이 있네요.

  UPDATE /*+ BYPASS_UJVC */
  (SELECT
   월계.기초재고미착    월계_기초재고미착
  ,월계.기말재고미착    월계_기말재고미착
  ,(월계.미착입점량+월계.미착반품량+월계.미착이동반입량) 월계_기말재고미착1
  ,MON.기말재고미착 MON_기말재고미착
   FROM (SELECT * FROM 영업매장월계
WHERE 발생일자 = NEXT_YYYYMM
   AND 품번 = 변_품번
   AND 사이즈   = 변_사이즈
   AND 색상 = 변_색상
   AND 매장코드 = 변_매장코드
   AND 매장존   = 변_매장존   
) 월계
   ,(SELECT * FROM 영업매장월계
WHERE 발생일자 = YYYYMM
   AND 품번 = 변_품번
   AND 사이즈   = 변_사이즈
   AND 색상 = 변_색상
   AND 매장코드 = 변_매장코드
   AND 매장존   = 변_매장존
    ) MON
   WHERE  월계.품번 = MON.품번
AND  월계.사이즈   = MON.사이즈
AND  월계.색상 = MON.색상   
AND  월계.매장코드 = MON.매장코드
AND  월계.매장존   = MON.매장존
   )
   SET
   월계_기초재고미착  =  MON_기말재고미착,
   월계_기말재고미착  =  MON_기말재고미착 + 월계_기말재고미착1;

계속 (ORA-01779 cannot modify a column which maps to a non key-preserved table)
오류를 뱉어내더군요....

음 이런식의 UPDATE 쿼리구요.. 이리저리 검색결과..
BYPASS 힌트는 11G R2부터는 사용 할 수 없는 힌트가 되버렸다는 것을 알았습니다.

해결방법을 찾던 도중.. MERGE를 이용하기로 하고....

  MERGE INTO (SELECT *
   FROM 영업매장월계
  WHERE 발생일자 = NEXT_YYYYMM
    AND 품번 = 변_품번
    AND 사이즈   = 변_사이즈
    AND 색상 = 변_색상
    AND 매장코드 = 변_매장코드
    AND 매장존   = 변_매장존
  ) 월계

  USING (SELECT *
   FROM 영업매장월계
  WHERE 발생일자 = YYYYMM
    AND 품번 = 변_품번
    AND 사이즈   = 변_사이즈
    AND 색상 = 변_색상
    AND 매장코드 = 변_매장코드
    AND 매장존   = 변_매장존
    ) MON

  ON (   월계.품번 = MON.품번
AND 월계.사이즈   = MON.사이즈
AND 월계.색상 = MON.색상
AND 월계.매장코드 = MON.매장코드
AND 월계.매장존   = MON.매장존)

  WHEN MATCHED THEN
    UPDATE
   SET 월계.기초재고미착 = MON.기말재고미착,
   월계.기말재고미착 = MON.기말재고미착 + 월계.미착입점량
    + 월계.미착반품량
    + 월계.미착이동반입량

  WHEN NOT MATCHED THEN
    INSERT(발생일자, 매장코드, 매장존,     품번, 색상, 사이즈,
   기초재고, 기초재고미착, 기말재고,   기말재고미착, 기초재고금액, 기말재고금액)
    VALUES(NEXT_YYYYMM,   MON.매장코드, MON.매장존,   MON.품번,   MON.색상, MON.사이즈,
   MON.기말재고,  MON.기말재고미착, MON.기말재고, MON.기말재고미착,  MON.기말재고금액, MON.기말재고금액);

이런식으로 쿼리를 변경을 하였습니다.

헌데.. 위 MERGE 쿼리중 빨간부분의 년월 변수때문에 ORA-600 오류를 뱉어내네요;;

빨간부분을 변수를 안쓰고 직접 '201104' 이런식으로 쓰면 잘 돌아가구요..

혹시 제가 실수한 부분이 있을까요??

오류는 ORA-00600 : INTERNAL ERROR CODE, ARGUMENTS:[qcsfbdnp:1],[],[],.... 입니다..

변수관련 오류인 것으로 판단하여 변수 타입 등등 다시확인해보았지만 이미 10g에서 잘 실행되던
구문이기에 문제가 없어 보입니다.

의견 부탁드리겠습니다^^

by 람짱 [2011.04.29 11:30:32]
위 두가지 쿼리가 모두 되지 않는다면..
일반 업데이트문을 쓰는 방법뿐이 없는데..
그렇게 된다면 시간이 많이 걸리게 되버립니다..
흠 꼭 해결했으면 합니다..

by 람짱 [2011.04.29 11:34:46]
참고로 yyyymm 변수는 프로시저 호출시 파라미터로 받아오는 값이며
next_yyyymm은 아래쿼리로 프로시저내에서 할당받습니다.

SELECT
TO_CHAR(ADD_MONTHS(TO_DATE(YYYYMM||'01'), 1),'YYYYMM')
INTO NEXT_YYYYMM
FROM DUAL;

by 마농 [2011.04.29 12:34:46]
TO_CHAR(ADD_MONTHS(TO_DATE(MON.발생일자, 'yyyymm'), 1), 'yyyymm')

by 람짱 [2011.04.29 12:38:23]
답변 감사합니다.

헌데 mon.발생일자도 yyyymm으로 가져오는 값입니다.
즉 yyyymm과 next_yyyymm이 전부 구해진 후 update를 하는 것이지요.

그리고 컬럼명이 발생일자지만 년월까지만 있는 컬럼입니다.

by 람짱 [2011.04.29 12:41:47]
그리고 일반 update, 혹은 insert 문으로 변경하여 실행하면 아무 문제 없이 실행이 되네요.. 다만 시간이 엄청 걸리는게 문제구요.ㅎ;;;

이걸로 봐서는 변수쪽 문제는 없는듯 하구요...

다시 말해서

a := '201104'
로 할당해서 yyyymm 대신에 a를 넣고 실행하면 에러가 발생합니다.

즉 merge문에서 문제가 있는듯 합니다.

by 마농 [2011.04.29 13:09:40]
USING (SELECT '201104' ym, ...) mon
...
VALUES(mon.ym, ...)
;

by 람짱 [2011.04.29 13:40:50]
NEXT_YYYYMM을 변수로 안받고

NEXT_YYYYMM대신

TO_CHAR(ADD_MONTHS(TO_DATE(YYYYMM||'01'), 1),'YYYYMM')
을 직접 쓰면.. 오류가 안나네요...;;

왜이럴까요;;;;

마농님 감사합니다^^;

by 마농 [2011.04.29 14:31:16]
버그라고 생각됩니다.
댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입