오라클 쿼리 질문이있습니다. 0 8 2,912

by 케빈재브라위너 [SQL Query] 오라클 [2024.01.24 14:40:02]


UPDATE 
               첫번째테이블 A
           SET A.고유번호 = ( SELECT B.고유번호
                                    FROM 두번째테이블 B
                                   WHERE B.사번 = A.사번
                                     AND COALESCE(A.고유번호, '-') != COALESCE(B.고유번호, '-')
                                );

- A테이블 데이터 100건(PK:사번)

- B테이블 데이터 50건 (PK: 사번, 고유번호)

 

라는 쿼리가

A테이블과 B테이블의 사번이 같고

A테이블의 고유번호 값과 B테이블의 고유번호 값이 같지않으면(A테이블의 값은 Null일 수도 있어서 Coalesce 처리했음)

A테이블의 고유번호값을 B테이블의 데이터로 덮어쓰겠다.

라고 이해가 가는데,

 

해당쿼리는 실제로 A테이블과 B테이블의 데이터가 다른게 1건이어도, 

A테이블에서 가지고있는 전체 데이터의 갯수만큼 업데이트가 되어서요.

(이래버리니, 해당 데이터가 변경된지 안된지 알수 있는 '최종수정일','최종수정자' 등의 정보도 전부 업데이트가 되어버림..)

 

아래 쿼리는 실제로 동작하지는 않지만,(오류발생하는게 맞는데, 제가 원하는 로직을 이해시키기위한 가상쿼리)

아래쿼리처럼 실제로 A테이블과 B테이블의 데이터가 다른것들만 업데이트 되게 할 수가 있을까요?

 

UPDATE 
               첫번째테이블 A
           SET A.고유번호 = ( SELECT B.고유번호
                                    FROM 두번째테이블 B
                                   )

     WHERE B.사번 = A.사번
        AND COALESCE(A.고유번호, '-') != COALESCE(B.고유번호, '-');
 

 

실제로 저렇게 첫번째 쿼리처럼 배치가 수행되도 업데이트가 안되고있어서 여쭤봅니다.

by 마농 [2024.01.24 15:36:35]

WHERE 절은 (select/update/delete) 대상을 제한하는 역할을 합니다.
WHERE 절이 없는 UPDATE 문이라면 당연히 전체 대상 업데이트 하게 됩니다.
SET 절에서 사용한 서브쿼리를 WHERE 절에 적용시키셔야 합니다.
IN 이나 EXISTS 형태로 적용시키면 됩니다.
다만, 지금 업데이트 조건이 틀린 것 같습니다.
B 테이블에 고유번호가 하나 뿐이라면? 문제가 없을 수도 있는데.
두개 이상이면 이상한 구문이 됩니다. 논리적으로 말이 안되는 구문이 됩니다.


by 케빈재브라위너 [2024.01.24 15:46:57]

UPDATE 
               첫번째테이블 A
           SET A.고유번호 = ( SELECT B.고유번호
                                    FROM 두번째테이블 B
                                   WHERE B.사번 = A.사번
                                     AND COALESCE(A.고유번호, '-') != COALESCE(B.고유번호, '-')
                                );

 

이 쿼리가 지금 조건이 틀린거같다라는 말씀이신건가요?

아니면 밑에 WHERE절을 IN이나 EXISTS로 적용시킬 가상쿼리의 조건이 틀렸다는건가요?

 


by 마농 [2024.01.24 15:49:19]

둘 다 해당됩니다.
1. WHERE 조건 누락
2. 서브쿼리 조건이 이상함
사번 하나당 고유번호가 여러개 가능하다면? 이상한 쿼리입니다.
B 테이블의 PK 가 (사번) 이라면 문제 없지만
B 테이블의 PK 가 (사번,고유번호) 라면 문제 됩니다.


by 케빈재브라위너 [2024.01.24 15:57:38]

UPDATE 
               첫번째테이블 A
           SET A.고유번호 = ( SELECT B.고유번호
                                    FROM 두번째테이블 B
                                   WHERE B.사번 = A.사번
                                     AND COALESCE(A.고유번호, '-') != COALESCE(B.고유번호, '-')
                                );

- A테이블 데이터 100건(PK:사번)

- B테이블 데이터 50건 (PK: 사번)

 

확인해보니 이렇게 되네요.

그런데 UPDATE쿼리가 수행은 정상적으로 되는데

실제로 업데이트가 안되는 ROW들이 있는데 이런경우는 어떤부분을 생각해 볼 수 있을까요?


by 마농 [2024.01.24 16:15:39]

위 구문은 오류입니다.
오라클이라면 다음과 같이 사용하셔야 합니다.
 

UPDATE 첫번째테이블 A
   SET A.고유번호 = (SELECT B.고유번호
                       FROM 두번째테이블 B
                      WHERE B.사번 = A.사번
                        AND COALESCE(A.고유번호, '-') != COALESCE(B.고유번호, '-')
                     )
 WHERE EXISTS (SELECT 1
                 FROM 두번째테이블 B
                WHERE B.사번 = A.사번
                  AND COALESCE(A.고유번호, '-') != COALESCE(B.고유번호, '-')
               )
;

-- http://gurubee.net/article/79308

 


by 케빈재브라위너 [2024.01.24 16:26:33]

아...

이렇게 WHERE조건을 추가함으로서 

해당되는 건들에 대해서만 업데이트가 가능하군요..

1건업데이트하는데 굳이 모든 로우에 대해서 수행될 필요없이...

 

그리고 조건을 추가하는게

필수인거네요 링크올려주신 팁 보니까...

둘중에 하나만 처리하는게아니네요 정말감사합니다.

 

마지막으로 하나만 여쭤보겠습니다.

"위 구문은 오류입니다" 라고하셨는데

수행시 수행이 안되는 오류가 아니라,

기존에 제가 작성했던 부정확한 SQL 작성 자체가 오류라는 말씀이신거죠?

 

이게 궁금한 이유는 배치가 돌면서

어떤 ROW는 정상수행되는데 어떤 ROW는 수행이력만 업데이트되고 실제 변경되어야할 SET 구문에 들어간 컬럼은

변화가 없어서요

 

아예 에러가 나면 수행자체가 안되어야할텐데 왜 되면서 정상수행을 하지못할까가 의문이었거든요

 

 


by 마농 [2024.01.24 17:03:48]

1. 제가 잘못 봤습니다.
- 구문 오류는 아니네요.
- 의미 오류입니다.
2. 한가지 더 팁을 드리자면
- UPDATE 쿼리를 바로 작성하여 실행하지 마시고
- 똑같이 생긴 SELECT 쿼리로 사전 확인 필수입니다.
 

-- 1. Update 대상 확인용 쿼리 --
SELECT A.사번
     , A.고유번호
     , (SELECT B.고유번호
          FROM 두번째테이블 B
         WHERE B.사번 = A.사번
           AND COALESCE(A.고유번호, '-') != COALESCE(B.고유번호, '-')
        ) 고유번호_NEW
  FROM 첫번째테이블 A
 WHERE EXISTS
       (SELECT B.고유번호
          FROM 두번째테이블 B
         WHERE B.사번 = A.사번
           AND COALESCE(A.고유번호, '-') != COALESCE(B.고유번호, '-')
        )
;

-- 2. Update 쿼리 --
UPDATE 첫번째테이블 A
   SET A.고유번호
     = (SELECT B.고유번호
          FROM 두번째테이블 B
         WHERE B.사번 = A.사번
           AND COALESCE(A.고유번호, '-') != COALESCE(B.고유번호, '-')
        )
 WHERE EXISTS
       (SELECT B.고유번호
          FROM 두번째테이블 B
         WHERE B.사번 = A.사번
           AND COALESCE(A.고유번호, '-') != COALESCE(B.고유번호, '-')
        )
;

 


by 케빈재브라위너 [2024.01.25 07:11:51]

아 감사합니다 

매번 찾아올때마다 답변해주시는게 너무 대단하고 존경스럽습니다

좋은 하루되세용!!! :)

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