문제6. SQL / 새로운 컬럼에 값을 갱신할 때 null값 없애기
[코드를 쓴 상황]
merge문을 이용해서 emp테이블과 dept테이블을 조인 후 dept 테이블의 sumsal 컬럼을 갱신하려고함.
dept 테이블에서 조인되지 않은 데이터는 null으로 갱신되는데, 이때 null 대신에 0값이 출력되게 하려고 함.
(단, 이때 dept테이블에 사전에 sumsal컬럼을 만들어야 함)
[내가 쓴 코드 + 에러]
merge into dept d
using (select deptno, sum(sal) as sumsal
from emp
group by deptno ) v
on (d.deptno = v.deptno)
when matched then
update set d.sumsal = v.sumsal
when not matched then
insert (d.deptno, d.sumsal)
values (v.deptno, 0);
1. merge문에 when not matched then을 써서 null을 0으로 대치하려했으나 코드가 실행되지 않음. matched된 데이터만 실행될 뿐 not matched된 데이터는 여전히 null로 출력됨.
2. emp테이블에 입력된 deptno는 10,20,30 뿐임. dept테이블에 입력된 deptno는 10,20,30,40.
when not matched할 때 insert(d.deptno, d.sumsal)
values(v.deptno, 0 ) <- v.deptno에 입력되는 값 자체가 30까지만 입력됨. 40이 없음.
따라서, 서브쿼리에서 불러온 데이터에 40이라는 데이터 자체가 없기 때문에 when not matched가 실행되지 않은 것.
[다른 사람이 쓴 코드]
-- 선생님이 쓴 코드
merge into dept d
using (select deptno, sum(sal) as sumsal
from emp
group by deptno ) v
on (d.deptno = v.deptno(+))
when matched then
update set d.sumsal = nvl(v.sumsal,0) ;
아우터조인해서 데이터를 열어주고 update set 절에 nvl함수를 사용하여 null을 0으로 대치함.
-- 다른 사람이 쓴 코드 1
merge into dept d
using (select deptno, sum(sal) as sumsal
from emp
group by deptno
union all
select 40, 0
from dual) e
on(d.deptno=e.deptno)
when matched then
update set d.sumsal=e.sumsal;
40,0 이라는 테이블과 emp테이블을 집합연산자 union all을 사용하여 위아래로 연결시킨 후, dept테이블과 조인함.
> emp+(40,0) 테이블이 dept테이블과 deptno 데이터 값이 일치하므로 null이 출력되지 않음.
[해결]
1. merge문에서 조인할 때, equi/non equi join만 생각하지 말 것. 1999 ansi join, 집합연산자 등 다양하게 테이블을 결합하여 merge문을 작성할 수 있음.
2. 연결고리 컬럼의 데이터들을 확인할 것 > when not matched를 같이 써도 가능한 데이터인지 확인 + 아우터조인여부
[다시 쓴 코드]
merge into dept d
using (select deptno, sum(sal) as sumsal
from emp
group by deptno ) v
on (d.deptno = v.deptno(+))
when matched then
update set d.sumsal = nvl(v.sumsal,0);