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 절이 실행되면서 같은 값이 있을때 위배된다고 나오는?느낌적인 느낌? 개발자의 직감?이 드는데 도통 처리가 안되고 답답하여 글 남겨 봅니다~
점심을 체할거 같네요...;;;
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 를 이용하는 것이 좋음.