오라클 merge의 on이 항상 true가 나옵니다 0 9 2,010

by 신고의추 [Oracle 기초] [2015.12.10 08:58:51]


merge into test_student a
        --비교하려는 서브쿼리생성 ( student와 professor의 prof_no이 같고
        --교수이름이'김규탁' 인 학생의 이름(stu_name)을 반환)
           using (select stu_name from test_student c, test_professor d
           where c.prof_no=d.prof_no and d.prof_name='김규탁') b

        -- test_student와 생성된 서브커리 결과의 stu_name이 서로 같은 자료가 있으면 update, 
        -- 아니면 insert
           on (a.stu_name=b.stu_name)
 when matched then
           update set a.prof_no=3
           where a.stu_name=b.stu_name
 when not matched then
           insert (stu_no,stu_name,dept_code, grade, phone_no,prof_no) 
           values('2012345','테스터',2,3,'010-9999-9999','');

======== 테이블 구조

test_professor(prof_no[PK],prof_name)

test_student(stu_no, stu_name, prof_no[FK])

============

on절이 잘못된건지 서브쿼리가 잘못된건지 잘 모르겠습니다.

insert는 확인하려고 추가한거라 상관이 없는 내용인데

on 을 where처럼 true/false가 나오게 작성을 한 것 같은데 항상 true가 나옵니다.

using 의 selet 를 따로 빼서 실행하면 결과값이 아무것도 나오지 않는데도 true가 나옵니다.

혹여나 해서 using에서 count 를 하게 한 뒤 count>0 이면 true가 나오게 했습니다.

그래도 역시나 count는 0인데 true로 빠져버리네요.

인터넷을 찾아봐도 다 조인조건/where/if 처럼 써라. true/false 형태에 따라 달라진다.

이런 설명뿐이라 도저히 이해가 안됩니다.

실행순서에 문제가 있는걸까요, 조건에 문제가 있는걸까요 ?

 

by 아발란체 [2015.12.10 09:28:09]

Using 이후 구문만 실행해보셨다면,

이전 구문까지 포함하여, Using 기준 앞 A, 뒤 B로 구분하여 조인해보세용~ 별 도움이 뉴.뉴)/


by 신고의추 [2015.12.10 10:15:45]
답변감사합니다.

select * from test_student a,
                    (select stu_name from test_student c, test_professor d
                    where c.prof_no=d.prof_no and d.prof_name='김규탁') b
          where a.stu_name=b.stu_name;

 

이런식으로 조인을 하라고 하신게 맞는지 모르겠네요.

On의 내용을 a와 b 테이블의 조인조건으로 넣었습니다.

조인 결과값은 '김규탁' 교수가 가르치는 학생이 있으면 데이터가 있고

없으면 아무런 데이터가 없습니다.

저는 이 아무런 데이터가 없을 때 insert로 넘어가길 바랬던거구요.


by 마농 [2015.12.10 09:38:29]

Using 절에 기술된 자료를 대상으로 INTO 절에 기술된 자료에 Merge 합니다.
Using 절에서 이미 머지대상 테이블과 조인하여 true 인것만 걸러냈으니.
on 절에서는 항상 Matched 일 수밖에 없죠.


작성한 머지 구문은 전반적으로 로직이 이상하네요.
일반적인 머지구문 사용법이 아닙니다.
다음 구문을 보고 Merge 의 개념을 잡아보세요.

MERGE INTO emp2 a
USING emp1 b
ON (a.empno = b.empno)
WHEN MATCHED THEN
    UPDATE SET a.ename = b.ename
WHEN NOT MATCHED THEN
    INSERT(empno, ename) VALUES(b.empno, b.ename)
;

 


by 신고의추 [2015.12.10 10:07:55]

답변 감사합니다. 하지만 저는 잘 이해가 되질 않네요.

using의 서브쿼리 결과값이 아무것도 나오지 않아도 On절에선 true값이 나오게 되는건가요?

아직 순서와 조건이 잘 이해가 가질 않습니다.

into의 테이블a와 using의 테이블b를 on에서 조건에 맞는 자료가 있으면 true, 없으면 false가 나오는것이 아닌가요?

on의 조인컨디션이 무엇을 뜻하는지도 잘 모르겠습니다.

on의 조건에 따라 테이블a와 테이블b를 조인을 하고, 조인한 결과에 데이터가 있으면 true, 없으면 false가 되는것인가요?

 


by 마농 [2015.12.10 10:13:33]

Using 절의 결과가 없다면? 머지 결과도 없죠.
Using 절의 결과 건수만큼 Into 테이블에 머지를 시도합니다.


Into 절과 Using 절, On 절의 역할을 명확하게 이해하셔야 합니다.
Using 절에 있는 데이터들을 대상으로
Into 절에 있는 데이터를 On 절로 비교 검색합니다.
Using 의 데이터가 Into 에도 있으면 Matched 없으면 Not Matched 입니다.


by 신고의추 [2015.12.10 10:25:46]

상세한 답변 감사합니다. 이제 감이 잡히는 듯 합니다.

제가 이해한 것이 맞는지 확인 부탁드립니다.

---

using의 테이블B의 데이터의 갯수만큼 on 조건 비교를 시도합니다.

따라서, B의 데이터가 없으면 비교할 횟수가 0이기에 false가 나오질 않아 update문으로 가게되고,

B의 데이터가 있으면 on조건에 따라 비교를 시도하고 해당하는 값이 하나라도 없으면 false,

해당하는 값이 하나라도 있으면 true가 나오게 됩니다.

---

이렇게 이해를 하였는데 맞는 것인가요 ?  


by 마농 [2015.12.10 10:42:00]

전혀 엉뚱한 이야기를 하고 계신 것 같네요.
말씀 하시는 True / False 의 의미가 뭘까요?


1. B의 데이터가 없으면 비교할 횟수가 0이기에 false가 나오질 않아 update문으로 간다???
==> B의 데이터가 없으면 아무 짓도 안합니다.


2. B의 데이터가 있으면 on조건에 따라 비교를 시도하고
해당하는 값이 하나라도 없으면 false,
해당하는 값이 하나라도 있으면 true가 나오게 됩니다?????
==> "하나라도" 라는 표현을 사용한 이유가 뭘까요?
On 절을 전체 대상으로 한 조건으로 착각하신 듯
Using 절릐 결과 건수만큼 건별로 각각 비교합니다.
10건 중 5건은 true 이고 5건은 False 라면?
5건은 Update, 5건은 Insert 되는거죠.


설명이 어려울 수 있으니 예를 들어 보일께요.
emp1 테이블에 (1, A), (2, B), (3, C) 3건의 자료가 있고
emp2 테이블에 (2, X), (4, Y) 2건의 자료가 있다면?
위에 제가 제시함 머지 구문을 실행하면...
2번과 4번 2건이 머지됩니다.
2번은 Matched 되어 Update 되고
4번은 Not Matched 되어 Insert 됩니다.
최종 결과는
emp1 테이블에 (1, A), (2, X), (3, C), (4, Y) 4건의 자료가 존재하게 되는 거죠.


by 신고의추 [2015.12.10 11:23:06]

정말 감사합니다 !!

설명해주신 것을 보고 코드를 새로 작성해보았더니 원하는 결과값이 나왔습니다!

제가 이상한 곳으로 이해를 하려했었네요.

답답하셨을텐데 친절한 답변과 자세한 설명 감사드립니다.

좋은 하루 되세요 !


by 마농 [2015.12.10 11:00:32]

이제 뭘 하고자 하는지 이해가 가네요.
Using 절의 결과가 있냐? 없냐? 를 가지고 True / False 를 말한 거였군요.
Using 절의 결과가 Into 에도 있냐 없냐를 가지고 각 행마다 True / False 를 따져야 합니다.


김규탁 교수가 가르치는 학생이 있으면 그 학생정보를 갱신하고
학생이 없으면 학생을 한명 추가 입력하는거네요.
예시 자체가 머지에 적합하지 않긴 한데요... 일단 머지구문 만들어 보면 다음과 같습니다.

MERGE test_student a
USING (SELECT prof_no, prof_name FROM test_professor WHERE prof_name = '김규탁') b
ON (a.prof_no = b.prof_no)
WHEN MATCHED THEN
    UPDATE SET a.xxx = 3
          -- , a.prof_no = 3    -- On 절의 비교 항목 prof_no 는 변경 불가함
             , a.prof_name = b.prof_name
WHEN NOT MATCHED THEN
    INSERT ...
;

 

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