oracle Merge into 질문 동작불량인지... 0 12 2,308

by 개발고수가되기를 [SQL Query] [2019.10.14 12:47:07]


MERGE INTO T_030 A
USING DUAL
ON ( A.NO_KEY = '13687100' )
WHEN MATCHED THEN
    UPDATE
           SET A.CD_CAR = '24루2048' ,
           A.NM_DESC = 'I TestI TestI Test' ,
           A.NO_UUSER = '000047' ,
           A.DT_UDATE = SYSDATE  

WHEN NOT MATCHED THEN
    INSERT 
           ( 
               A.NO_KEY ,
               A.CD_CAR ,
               A.NM_DESC,
               A.NO_IUSER,
               A.DT_IDATE,
               A.NO_UUSER,
               A.DT_UDATE --수정일자 
           )
           VALUES 
           (
               '13687100' ,
               '24루2048' ,
               'I TestI TestI Test' ,
               '000047' ,
               SYSDATE ,
               '000047' ,
               SYSDATE
           ) 

 

 

 

위와 같은 머지문을 사용하고 있습니다.

사실 오늘 처음 사용하긴 합니다만

insert는 잘 되는데 update가 될때

"Message : ORA-00001: 무결성 제약 조건(Z.PK_T_030)에 위배됩니다"

가 나옵니다.

 

그래서 console 창에 해당 쿼리를 가져와서 실행하면 update가 곧 잘 됩니다.

구문이나 제가 잘못 작성한게 있을까요?

뭔가 insert 절이 실행되면서 같은 값이 있을때 위배된다고 나오는?느낌적인 느낌? 개발자의 직감?이 드는데 도통 처리가 안되고 답답하여 글 남겨 봅니다~

점심을 체할거 같네요...;;;

by 마농 [2019.10.14 13:01:59]

콘솔에서 실행하면 잘된다? --> 쿼리엔 문제가 없네요.
프로그램에서 사용하면 안되는 거라면? --> 프로그램 코딩 실수가 있을 듯 하네요.
실행 로그를 찍어 보세요. 디버깅 해보세요.


by 개발고수가되기를 [2019.10.14 13:03:16]

프로그램에서는 무결성 제약조건이 위배된다고 콘솔에 찍히고요...

그걸 그대로 복사해서 sql 툴에서 실행하면 업데이트가 되네요 이럴수가 있나요...?

참으로 답답한데 다시 작성하고 이짓 저짓 해봐도 같네요ㅠ


by jkson [2019.10.14 13:11:56]

프로그램에서 코딩 오류로 2번 수행된 것 아닐까요?


by 개발고수가되기를 [2019.10.14 13:36:06]

실행은 한번만 딱 되네요...ㅠㅠ


by 마농 [2019.10.14 13:18:16]

머지문 외에 다른 인서트 구문이 다시 실행되고 있지는 않은지?
디버깅 해보세요.


by 개발고수가되기를 [2019.10.14 13:31:14]

네 계속 trace 찍어 보고 있는데 merge 문에서 데이터가 있음에도 불구하고 insert 까지 실행이 쭉 되다가 중간에 걸리는거 같은 느낌이 듭니다

혹시 프로그램에서 디버깅하시는 노하우좀 간단하게 여쭤도 될까요?


by 개발고수가되기를 [2019.10.14 14:06:06]

아고 처리 했습니다

ON 절에 TRIM을 걸어 하니 처리가 잘 됩니다!!! TRACE 찍을때도 빈칸도 없고 실제 TOOL에서도 그냥 했을때 되었는데 이유는 모르겠네요...

이렇게 처리할때 이유라도 알면 참 좋겠지만...

혹시 정확히 알게되면 다시 글 한번 남기겠습니다.

어렵네요...


by 마농 [2019.10.14 14:16:31]

data type 이 char 인가보네요?
varchar2 를 권고하는 이유 중에 하나죠.


by 꼬랑지 [2019.10.14 14:16:33]

T_030 테이블의 PK가 무엇인가요?

증상으로만 보면 프로그램에서는 머지문이 INSERT가 실행되고 로그에 있는 쿼리를 실행하면 UPDATE가 실행되는 느낌인데

해당 쿼리를 호출하는 프로그램의 메소드에 T_030 테이블을 핸들링하는 쿼리문이 이 머지문 하나만 있나요?

그리고 혹 T_030 테이블에 트리거가 걸려 있는건 없나요?


by 마농 [2019.10.14 15:01:08]

a.no_key 가 CHAR(10) 이라고 가정하면
최초 '13687100' 이 입력되면 실제로 '13687100  ' 이 들어가게 됩니다.
이상태로 a.no_key = '13687100' 로 비교하면.
툴에서는 상수로 비교하니 참이 되는 것이고
프로그램에서는 바인드 변수로 비교하면 거짓이 됩니다.
a.no_key = '13687100'  -- 참 : 상수의 경우 공백까지 감안하여 알아서 비교해 줌
a.no_key = :v_no_key   -- 거짓 : 변수의 경우 값 그대로 비교하여 공백차이로 인해 거짓이 됨.
거짓이므로 NOT MATCHED THEN 문을 타서 INSERT 되게 됨.
INSERT 될 때 또 공백 붙여서 입력되면서 기존값과 동일하여 에러 발생.
TRIM 을 이용할 경우 해당 오류는 잡을 수 있지만
인덱스를 이용하지 못하므로 성능상 문제의 소지가 있음.
컬럼에 TRIM 하지 말고 조건에 RPAD 하여 인덱스를 이용하도록 해야 함.
 - 변경전 : TRIM(a.no_key) = :v_no_key
 - 변경후 : a.no_key = RPAD(:v_no_key, 10, ' ')
물론 이렇게 하는 것 보다는 CHAR 대신 VARCHAR2 를 이용하는 것이 좋음.


by 개발고수가되기를 [2019.10.16 17:31:10]

또 배우네요

mssql에서 가져오는 값 no는 int고 no_key는 오라클의 varchar2네요

이런거 생각안해봤는데 이번에 어쩃는 제가 처리 했지만 어렵습니다...개발...


by 생각 [2019.10.15 11:20:32]

CHAR형 이면 그렇죠. 저도 자주 겪는 일입니다^^;;

특히 외부솔루션 연동시에 VARCHAR형이 아니면 대부분 TRIM(CHAR형) 해줘야 문제가 없더군요.

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