쿼리좀 봐주세요.. 0 6 2,620

by 약쟁이총각 [SQL Query] [2013.02.19 15:09:18]


개발중에 다음의 쿼리를 돌릴때 에러가 발생합니다.

UPDATE /*+ bypass_ujvc +*/
(SELECT A.CLASS_NAME A_CLASS_NAME, B.CLASS_NAME B_CLASS_NAME FROM sso_user_incs A, sso_user B WHERE A.USER_ID = B.USER_ID AND B.CLASS_NAME <> ' ')
SET A_CLASS_NAME = B_CLASS_NAME

=== 에러 ====
ORA-01779: cannot modify a column which maps to a non key-preserved table

키 값이 중복이 날때 나는 에러라 하는데.. 무엇인지 찾아보아도 잘 모르겠네요..

SELECT A.CLASS_NAME A_CLASS_NAME, B.CLASS_NAME B_CLASS_NAME FROM sso_user_incs A, sso_user B WHERE A.USER_ID = B.USER_ID AND B.CLASS_NAME <> '  '  <==== 이렇게만 돌리면 결과값이 잘 나옵니다.

이런경우를 보신분은.. 답변 부탁드립니다.

by 아발란체 [2013.02.19 15:26:40]
키가 보존되지 않은 상태로 발생하는 에러입니다.
조건절에 들어가는 항목이 키로 잡혀 있어야 합니다.


by 마농 [2013.02.19 15:32:54]
b.user_id 에 Unique Index 를 생성하세요.

by 약쟁이총각 [2013.02.19 15:44:56]

한가지 궁금한 것이 있는데요..

sso_user 테이블은  view로 생성이 되어있어서 인덱스를 걸 수가 없습니다.

중복값이 걸리는지 확인할 결과 중복이 없구요..

===== 질문 =====
1. 비교하는 테이블이 view 테이블이면 위의 구문은 쓸수 없나요??


2. 대신해서 다음의 구문은 만들어 봤었는데.. 에러가 발생하네요.. ㅜㅜ
처음 만들어 보는거라.. 무엇이 틀렸는지 알수 있을까요??

merge into sso_user_incs A
using (select * from sso_user where CLASS_NAME ' ') b
on (A.USER_ID = B.USER_ID)
when matched then
update set A.CLASS_NAME = B.CLASS_NAME

by 마농 [2013.02.19 15:48:32]

bypass_ujvc 힌트 없이 위 업데이트가 가능하려면
b.user_id 에 Unique Index 가 있어야만 합니다.
즉, 유니크인덱스가 a 와 b 의 관계가 1:1 또는 m:1 임을 보장해 주는 것입니다.
bypass_ujvc 힌트는 유니크인덱스가 없어도
명령어을 실행하는 사람이 이를 보장하겠다는 힌트입니다.
하지만 말로만 보장하고 실제로는 아닌 경우가 발생뒬 수 있으므로
bypass_ujvc 힌트는 비공식 힌트이며, 11g 부터는 아예 사용 불가합니다.
머지 구문을 이용하세요.
MERGE INTO a
USING b
ON (a.user_id = b.user_id)
WHEN MATCHED THEN
UPDATE SET class_name = b.class_name
;


by 약쟁이총각 [2013.02.19 16:59:07]
merge into sso_user_incs A
using (select user_id,class_name from sso_user where CLASS_NAME ' ') b
on (A.USER_ID = B.USER_ID)
when matched then
update set CLASS_NAME = B.CLASS_NAME

이렇게 하니까 ora-00905번이 발생하네요.. ㅜㅜ

찾아보니까 9i여서 나온 문제라 생각이 되네요..

merge into sso_user_incs A
using (select user_id,class_name from sso_user where CLASS_NAME ' ') b
on (A.USER_ID = B.USER_ID)
when matched then
update set CLASS_NAME = B.CLASS_NAME
when not matched then end;

테스트 불가능이어서 될지 모르겠지만 잘 되겠줘..ㅋㅋ

관심가져주셔서 감사합니다.

by 마농 [2013.02.19 17:17:46]
-- 9i 라면???
-- WHEN NOT MATCHED THEN 구문도 필수입니다만...
-- bypass_ujvc 힌트도 사용 가능 할 텐데요???
-- 일단 3가지 방법이 있습니다.
-- 1. 전통적인 오라클 업데이트
UPDATE sso_user_incs a
   SET class_name = (SELECT class_name FROM sso_user WHERE user_id = a.user_id AND class_name != ' ')
 WHERE EXISTS (SELECT 1 FROM sso_user WHERE user_id = a.user_id AND class_name != ' ')
;
-- 2. 머지 : Not Matched 상황이 발생하지 않도록 Using 절 조절
MERGE INTO sso_user_incs a
USING
(
SELECT b.user_id
     , b.class_name
  FROM sso_user_incs a
     , sso_user b
 WHERE a.user_id = b.user_id
   AND b.class_name != ' '
) b
ON (a.user_id = b.user_id)
WHEN MATCHED THEN
UPDATE
   SET class_name = b.class_name
WHEN NOT MATCHED THEN
INSERT(user_id, class_name)
VALUES(b.user_id, b.class_name)
;
-- 3. Bypass_ujvc 힌트 사용
댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입