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 절이 실행되면서 같은 값이 있을때 위배된다고 나오는?느낌적인 느낌? 개발자의 직감?이 드는데 도통 처리가 안되고 답답하여 글 남겨 봅니다~
점심을 체할거 같네요...;;;
콘솔에서 실행하면 잘된다? --> 쿼리엔 문제가 없네요.
프로그램에서 사용하면 안되는 거라면? --> 프로그램 코딩 실수가 있을 듯 하네요.
실행 로그를 찍어 보세요. 디버깅 해보세요.
프로그램에서 코딩 오류로 2번 수행된 것 아닐까요?
실행은 한번만 딱 되네요...ㅠㅠ
프로그램에서는 무결성 제약조건이 위배된다고 콘솔에 찍히고요...
그걸 그대로 복사해서 sql 툴에서 실행하면 업데이트가 되네요 이럴수가 있나요...?
참으로 답답한데 다시 작성하고 이짓 저짓 해봐도 같네요ㅠ
머지문 외에 다른 인서트 구문이 다시 실행되고 있지는 않은지?
디버깅 해보세요.
네 계속 trace 찍어 보고 있는데 merge 문에서 데이터가 있음에도 불구하고 insert 까지 실행이 쭉 되다가 중간에 걸리는거 같은 느낌이 듭니다
혹시 프로그램에서 디버깅하시는 노하우좀 간단하게 여쭤도 될까요?
아고 처리 했습니다
ON 절에 TRIM을 걸어 하니 처리가 잘 됩니다!!! TRACE 찍을때도 빈칸도 없고 실제 TOOL에서도 그냥 했을때 되었는데 이유는 모르겠네요...
이렇게 처리할때 이유라도 알면 참 좋겠지만...
혹시 정확히 알게되면 다시 글 한번 남기겠습니다.
어렵네요...
data type 이 char 인가보네요?
varchar2 를 권고하는 이유 중에 하나죠.
T_030 테이블의 PK가 무엇인가요?
증상으로만 보면 프로그램에서는 머지문이 INSERT가 실행되고 로그에 있는 쿼리를 실행하면 UPDATE가 실행되는 느낌인데
해당 쿼리를 호출하는 프로그램의 메소드에 T_030 테이블을 핸들링하는 쿼리문이 이 머지문 하나만 있나요?
그리고 혹 T_030 테이블에 트리거가 걸려 있는건 없나요?
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 를 이용하는 것이 좋음.
또 배우네요
mssql에서 가져오는 값 no는 int고 no_key는 오라클의 varchar2네요
이런거 생각안해봤는데 이번에 어쩃는 제가 처리 했지만 어렵습니다...개발...
CHAR형 이면 그렇죠. 저도 자주 겪는 일입니다^^;;
특히 외부솔루션 연동시에 VARCHAR형이 아니면 대부분 TRIM(CHAR형) 해줘야 문제가 없더군요.