Oracle 20강 - 서브쿼리

DML문 (UPDATE,INSERT,DELETE)

3)서브쿼리를 사용한 UPDATE문
(사용형식)
UPDATE 테이블명
SET (컬럼명[,컬럼명,...])=(서브쿼리) --변경할 컬럼들을 단일컬럼으로 기술했었음
[WHERE 조건];
. SET 절에 컬럼명이 복수개 사용되는 경우 컬럼명들을 '( )'로 묶어 기술하고
서브쿼리의 SELECT절의 컬럼list와 갯수, 순서, 타입이 일치해야 함
. 서브쿼리가 사용되는 SET절에 단일 컬럼을 처리하는 경우 복수개의 서브쿼리가 필요
--서브쿼리의 조건은 서브쿼리에서 변경할 값을 결정할 자료를 꺼내기 위한 조건
--WHERE 조건은 변경할 데이터를 만들어내기 위한 조건
--WHERE절은 행을 담당, 업데이트 할 행의 개수를 추출하는 조건

--업데이트 할 열은 하나인데 두개의 열 값이 서브쿼리 안에 있다면
-> 서브쿼리를 또 서브쿼리로 묶음

사용예)사원테이블에서 사원들의 급여를 소속부의 평균급여로 갱신하시오.

(서브쿼리:부서별 평균급여)
    SELECT DEPARTMENT_ID,
           ROUND(AVG(SALARY)) AS ASAL
      FROM HR.EMP
     GROUP BY DEPARTMENT_ID; 

(메인쿼리:사원의 급여 변경)
    UPDATE HR.EMP A
       SET A.SALARY=(SELECT B.ASAL
                       FROM (SELECT DEPARTMENT_ID,
                                    ROUND(AVG(SALARY)) AS ASAL
                               FROM HR.EMP
                              GROUP BY DEPARTMENT_ID)B
                      WHERE A.DEPARTMENT_ID=B.DEPARTMENT_ID); 
                      --사원이 가지고있는 부서만 구별, 사원이 구별될 필요는 없음
     WHERE A.DEPARTMENT_ID=50;
     

사용예)2005년 7월 사용자별 구매현황을 조회하여 회원들의 마일리지를 변경하시오
--구매활동을 한 결과에 따라 CART, MEMBER, PROD

(서브쿼리: 2005년 7월 사용자별 추가 지급될 마일리지)--회원번호,지급될 마일리지
  SELECT D.SUMM
    FROM (SELECT A.CART_MEMBER AS AID,
                 SUM(A.CART_QTY*B.PROD_MILEAGE) AS SUMM
            FROM CART A, PROD B
           WHERE A.CART_NO LIKE '200507%'
             AND A.CART_PROD=B.PROD_ID
           GROUP BY A.CART_MEMBER)D 
  
(메인쿼리: 갱신)
  UPDATE MEMBER C
     SET MEM_MILEAGE =(SELECT C.MEM_MILEAGE+D.MSUM --가지고 있는 마일리지에 더해지는 마일리지
                          FROM (SELECT A.CART_MEMBER AS AID,
                                       SUM(A.CART_QTY*B.PROD_MILEAGE) AS MSUM
                                  FROM CART A, PROD B
                                 WHERE A.CART_NO LIKE '200507%'
                                   AND A.CART_PROD=B.PROD_ID
                              GROUP BY A.CART_MEMBER)D
                          WHERE C.MEM_ID=D.AID)    --변경할 값
   WHERE C.MEM_ID IN (SELECT DISTINCT CART_MEMBER
   --MEM_ID가 더 많기 때문에 '='가 아닌 IN연산자가 나와야한다.
                        FROM CART
                       WHERE CART_NO LIKE '200507%');
                       -- 2005년 7월에 판매실적이 있는 회원들만 골라서 변경해라 
   --바깥쿼리의 where절 : 변경할 사람을 고르는 조건                     
   
   SELECT MEM_ID,MEM_MILEAGE
     FROM MEMBER;

사용예)2005년 5-7월 매출현황을 조회하여 재고수불테이블을 변경하시오

--서브쿼리
    SELECT CART_PROD,
           SUM(CART_QTY)
      FROM CART
     WHERE SUBSTR(CART_NO,1,6) BETWEEN '200505' AND '200507'  
     GROUP BY CART_PROD;

 --재고수불테이블 변경      

  UPDATE REMAIN A
   SET (A.REMAIN_O,A.REMAIN_J_99,A.REMAIN_DATE)=
       (SELECT A.REMAIN_O+B.CMT,A.REMAIN_J_99-B.CMT,TO_DATE('20050731')
          FROM (SELECT CART_PROD AS CID,
                       SUM(CART_QTY) AS CMT
                  FROM CART
                 WHERE SUBSTR(CART_NO,1,6) BETWEEN '200505' AND '200507'
                 GROUP BY CART_PROD) B
         WHERE A.PROD_ID=B.CID)
   WHERE A.PROD_ID IN (SELECT DISTINCT CART_PROD
                         FROM CART
                        WHERE SUBSTR(CART_NO,1,6) BETWEEN '200505' AND '200507'); 

사용예)2005년 5-7월 매입현황을 조회하여 재고수불테이블을 변경하시오
--서브쿼리 : 5-7월 매입현황

UPDATE REMAIN A      
   SET (A.REMAIN_I,A.REMAIN_J_99,A.REMAIN_DATE)=
       (SELECT A.REMAIN_I+B.BMT,A.REMAIN_J_99+B.BMT,TO_DATE('20050731') 
          FROM (SELECT BUY_PROD AS BID,
                       SUM(BUY_QTY) AS BMT
                  FROM BUYPROD
                 WHERE BUY_DATE BETWEEN TO_DATE('20050501') AND TO_DATE('20050731') 
                 GROUP BY BUY_PROD)B
         WHERE A.PROD_ID=B.BID)
 WHERE A.PROD_ID IN (SELECT DISTINCT BUY_PROD
                       FROM BUYPROD
                      WHERE BUY_DATE BETWEEN TO_DATE('20050501') AND TO_DATE('20050731')); 

집합연산자 사용하면 서브쿼리를 줄일 수 있음.

4)서브쿼리를 이용한 INSERT
(사용형식)
INSERT INTO 테이블명[(컬럼명[,컬럼명,...])]
서브쿼리;
. INSERT 에 사용되는 서브쿼리는 '( )'안에 기술하지 않음
. 서브쿼리를 사용하는 INSERT에는 VALUES 예약어가 생략

** 테이블 복사
CREATE TABLE 테이블명 AS
서브쿼리 --서브쿼리의 결과가 테이블에 들어옴

사용예)REMAIN 테이블을 REMAIN_TEMP테이블을 생성시키고 내용을 복사하시오.

 CREATE TABLE REMAIN_TEMP AS
   SELECT * FROM REMAIN; 
   --REMAIN테이블에 있는 모든 행과 열이 REMAIN_TEMP에 들어감

 SELECT * FROM REMAIN_TEMP; 

DELETE REMAIN_TEMP; --REMAIN의 모든 행을 삭제시킴
 (행을 담당하는 WHERE절이 생략되면 모든 행 삭제, TABLE 자체를 없애는 게 아님)

COMMIT;

사용예)재고수불테이블에서 현재고가 음수인 자료를 찾아 REMAIN_TEMP테이블에 저장하시오.

INSERT INTO REMAIN_TEMP
  SELECT * FROM REMAIN
   WHERE REMAIN_J_99<0;
   
 SELECT * FROM REMAIN_TEMP;  
     

좋은 웹페이지 즐겨찾기