Study/class note

sql중급 / 서브쿼리를 사용한 update, delete, merge

chanzae 2021. 11. 22. 15:26

ㅁ복습

SCOTT의 월급을 6700으로 수정하시오

update emp
set sal = 6700
where ename = 'SCOTT';

직업이 SALESMAN인 사원들의 커미션을 모두 5000으로 수정하시오

update emp
set comm = 5000
where job = 'SALESMAN';

ALLEN과 직업이 같은 사원들의 이름과 직업을 출력하는데 ALLEN은 제외하고 출력하시오

select ename, job
 from emp
 where job = (select job
               from emp
               where ename = 'ALLEN')
   and ename != 'ALLEN';

 

 

086 서브 쿼리를 사용하여 데이터 수정하기(서브쿼리를 사용한 update문)

update문에 서브쿼리를 쓸 수 있는 절 

 update 테이블명               -- 서브쿼리 가능

 set 변경할 컬럼과 값          -- 서브쿼리 가능

 where 조건                      -- 서브쿼리 가능

 

-- SMITH보다 더 많은 월급을 받는 사원들의 부서번호를 10번으로 수정하시오
update emp
set deptno = 10
where sal > (select sal
              from emp
              where ename = 'SMITH');

문제431. ALLEN보다 늦게 입사한 사원들의 커미션을 9000으로 수정하시오

update emp
set comm = 9000
where hiredate > (select hiredate
                   from emp
                   where ename = 'ALLEN');

문제432. ALLEN의 직업을 JONES의 직업으로 변경하시오

update emp
set job = (select job
            from emp
            where ename = 'JONES')
where ename = 'ALLEN';

문제433. SCOTT의 월급을 KING의 월급으로 변경하시오

update emp
set sal = (select sal
            from emp
            where ename = 'KING')
where ename = 'SCOTT';

문제434. ALLEN보다 늦게 입사한 사원들의 월급을 KING의 월급으로 변경하시오

update emp
set sal = (select sal
            from emp
            where ename = 'KING')
where hiredate > (select hiredate
                   from emp
                   where ename = 'ALLEN');

문제435. JONES보다 더 많은 월급을 받는 사원들의 부서번호를 ALLEN의 부서번호로 바꾸시오

update emp
set deptno = (select deptno
               from emp
               where ename = 'ALLEN')
where sal > (select sal
              from emp
               where ename = 'JONES');

update 절 테이블명에 서브쿼리를 사용하는 경우 > 주로 튜닝을 위해서 사용함.

문제436. 사원테이블에 SAL2라는 컬럼을 아래와 같이 수행해서 추가하시오

alter table emp
   add sal2 number(10);

문제437. 사원 테이블의 월급을 sal2에 그대로 업데이트 하세요

update emp
set sal2 = sal;

방금 추가한 sal2컬럼 삭제하기

alter table emp
  drop column sal2;
  
/*컬럼 추가/삭제 명령어

컬럼추가
alter table 테이블명
  add 컬럼명 테이터타입;
  
컬럼삭제
alter table 테이블명
 drop column 컬럼명;  */

문제438. emp와 dept를 조인해서 이름, 부서위치를 출력하시오

select e.ename, d.loc
 from emp e, dept d;

문제439. emp테이블에 loc컬럼을 추가하시오

alter table emp
  add loc varchar2(10);

문제440. (복습문제) merge문을 이용해서 emp테이블에 loc컬럼 값을 갱신하시오

merge into emp e
using dept d
on (e.deptno = d.deptno)
when matched then
update set e.loc = d.loc;

문제441. 이름, 사원 테이블의 부서위치(loc), 부서테이블의 부서위치(loc)를 출력하시오

select e.ename, e.loc, d.loc
 from emp e, dept d
 where e.deptno = d.deptno;

문제442. emp_loc컬럼의 데이터를 dept_loc컬럼의 데이터로 update하시오

update (select e.ename, e.loc as emp_loc, d.loc as dept_loc
         from emp e, dept d
         where e.deptno = d.deptno)
set emp_loc = dept_loc;
/* 에러 : ORA-01779: 키-보존된것이 아닌 테이블로 대응한 열을 수정할 수 없습니다
dept테이블의 primary key제약을 deptno에 걸면 됨
(primary key 제약은 뒤에서 배울 예정/ 21c primary key제약 없이 가능)
primary key 제약을 특정 컬럼에 걸면 중복된 데이터와 null값이 입력안됨

primary key 제약 거는 방법
alter table dept
add constraint dept_deptno_pk primary key(deptno);


-- 컬럼 별칭 반드시 사용해서 작성해야함

데이터 갱신 속도가 merge문 만큼이나 빨라서 튜닝 방법으로 많이 사용

 

문제443. 위의 update문을 rollback하고 다음의 악성 SQL로 loc컬럼을 갱신하시오

update emp e
set loc = (select loc
              from dept d
              where e.deptno = d.deptno);
              
/* emp테이블의 부서번호가 첫번재 행부터 서브쿼리로 들어와서 부서위치를 찾게 됨
> 모든 사원들에 대해 갱신해줘야 하므로 e.deptno=d.deptno 데이터의 갯수만큼 반복됨
> 따라서 성능을 위해 merge문을 사용하거나 update절의 서브쿼리를 사용해 튜닝하면 됨 */

문제444. 사원 테이블에 dname 컬럼을 추가하시오

alter table emp
add   dname  varchar2(10);

문제445. 사원 테이블의 dname을 부서테이블의 dname으로 변경하시오

update (select e.dname as emp_d, d.dname as dept_d
         from emp e, dept d
         where e.deptno = d.deptno)
set emp_d = dept_d;

문제446. telecom_service테이블의 telecom에 primary key제약을 거시오

alter table telecom_service
add  constraint telecom_service_pk primary key(telecom);
--                    제약이름     제약의 종류(제약이 걸리는 컬럼)

문제447. emp14테이블에 price라는 컬럼을 다음과 같이 추가하시오

alter table emp14
add price number(10);

문제448. (점심시간 문제) emp14테이블의 price컬럼에 값을 갱신하는데 telecom_service의 해당통신사의 price로 값을 갱신하시오

update (select e.price as emp_p, t.price as tel_p
          from emp14 e, telecom_service t
          where e.telecom = t.telecom)
set emp_p = tel_p;

 

ㅇ서브쿼리를 사용한 update문은 여러개의 데이터를 한번에 갱신할 수 있는 SQL인데 많은 양의 데이터를 갱신할 때는 튜닝된 SQL을 생각해야함.

그 튜닝된 SQL이 바로 merge문과 update절의 서브쿼리

 

 

087 서브 쿼리를 사용하여 데이터 삭제하기(서브쿼리를 사용한 delete문)

--복습예제. 월급이 3000 이상인 사원들을 삭제하시오
delete from emp
where sal >= 3000;

delete는 where절에만 서브쿼리 작성가능

--SCOTT보다 더 많은 월급을 받는 사원들을 삭제하시오
delete from emp
where sal > (select sal
              from emp
              where ename = 'SCOTT');

문제449. SCOTT과 같은 직업을 갖는 사원들을 삭제하는데 SCOTT은 제외하고 삭제하시오

delete from emp
where job = (select job
              from emp
              where ename = 'SCOTT')
   and ename <> 'SCOTT';

문제450. ALLEN보다 늦게 입사한 사원들을 모두 지우시오

delete from emp
where hiredate > (select hiredate
                   from emp
                   where ename = 'ALLEN');

 

문제451. (복습문제) 부서위치, 부서위치별 토탈월급을 출력하는데 부서위치별 토탈월급이 높은 것부터 출력하시오

select d.loc, sum(e.sal)
 from emp e, dept d
 where e.deptno = d.deptno
 group by d.loc;

문제452. (복습문제) 부서번호, 부서번호별 토탈월급을 출력하시오

select deptno, sum(sal)
 from emp
 group by deptno;

 

 

088 서브 쿼리를 사용하여 데이터 합치기(서브쿼리를 사용한 merge문)

예제. 사원테이블의 loc컬럼을 추가하고 loc컬럼의 데이터를 해당 사원의 부서위치로 값을 갱신하시오

alter table emp
 add loc  varchar2(10);
 
merge into emp e
using dept d
on (e.deptno = d.deptno)
when matched then
update set e.loc = d.loc;

문제453. dept테이블에 sumsal이라는 컬럼을 number(10)으로 추가하시오

-- emp테이블에 sumsal컬럼 삭제하는 명령어
alter table emp
drop column sumsal;


-- dept테이블에 sumsal컬럼 추가하는 명령어
alter table dept
add sumsal number(10);

문제454. 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;

문제455. 위의 결과에서 deptno 40번의 sumsal은 숫자 0으로 갱신되게 하시오

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) ;

 

문제456. dept테이블과 deptno_sumsal을 조인해서 부서위치를 출력하고 그 옆에 부서위치별 토탈월급이 출력되게 하세요

select d.loc, s.sumsal
 from dept d, deptno_sumsal s
 where d.deptno = s.deptno;

문제457. 위의 결과를 다시 출력하는데 outer join을 사용해서 다음과 같이 출력하세요

select d.loc, s.sumsal
 from dept d, deptno_sumsal s
 where d.deptno = s.deptno(+);

문제458. 위의 결과에서 sumsal이 null로 나오는 부분을 0으로 출력되게 하시오

select d.loc, nvl(s.sumsal,0)
 from dept d, deptno_sumsal s
 where d.deptno = s.deptno(+);

문제459. telecom_service테이블에 cnt라는 컬럼을 추가하시오

alter table telecom_service
 add cnt number(10);

문제460. 우리반테이블에서 통신사를 출력하고 통신사별 인원수를 출력하시오

select telecom, count(*)
 from emp14
 group by telecom;

문제461. telecom_service테이블에 cnt컬럼의 해당 통신사의 인원수로 값을 갱신하시오

merge into telecom_service t
using (select telecom, count(*) as cnt
        from emp14
        group by telecom ) v
on (t.telecom = v.telecom)
when matched then
update set t.cnt = v.cnt;

문제462. telecom_service테이블에 avg_age 컬럼을 추가하시오

alter table telecom_service
add  avg_age   number(10);

문제463. 우리반 테이블에서 통신사, 통신사별 평균나이를 출력하시오

select telecom, round(avg(age))
 from emp14
 group by telecom;

문제464. telecom_service테이블에 추가한 avg_age컬럼에 데이터를 통신사별 평균나이로 값을 갱신하시오

merge into telecom_service t
using (select telecom, round(avg(age)) as aa
        from emp14
        group by telecom) v
on (t.telecom = v.telecom)
when matched then
update set t.avg_age = v.aa;

문제465. 위의 결과를 악성 SQL로 작성하시오

update telecom_service t
set t.avg_age = (select round(avg(age))
                  from emp14 e
                  where e.telecom = t.telecom );

 

 

 

 

 

 

 

 

 

반응형