본문 바로가기
DBMS/ORACLE

WITH 문 사용(임시테이블, 프로시저, 펑션) 및 동작방식

by 드바 2022. 7. 1.

- WITH 절은 2가지 동작 방식이 있다.

Materialize 방식 : 임시 테이블을 생성 후 WITH 절의 결과를 저장하며, 반복 호출 시 쿼리를 실행하지 않고 임시 테이블에 저장된 결과를 사용한다.
Inline 방식 : 임시 테이블을 생성하지 않고 Inline View 형태로 수행하며, 참조된 횟수만큼 반복적으로 쿼리를 실행한다.
- 동작 방식은 (MATERIALIZE, INLINE) 힌트로 제어가능하다.
- 힌트 없을 시 2번 이상 수행되면 Materialize, 1회만 수행되면 Inline View 로 결정됨

 

WITH 절 임시테이블 선언

WITH EMP_W1 AS
(SELECT DEPARTMENT_ID, SUM(SALARY) AS SAL 
 FROM HR.EMPLOYEES
 GROUP BY DEPARTMENT_ID
)
SELECT A.DEPARTMENT_ID
, B.DEPARTMENT_NAME
, A.SAL
FROM EMP_W1 A, HR.DEPARTMENTS B
WHERE A.DEPARTMENT_ID = B.DEPARTMENT_ID
;

 

WITH 절 여러개 테이블 선언(쉼표로 구분)

WITH EMP_W1 AS
( 
  SELECT DEPARTMENT_ID
       , AVG(SALARY) AS SAL_AVG
    FROM HR.EMPLOYEES
   GROUP BY DEPARTMENT_ID
), 
EMP_W2 AS 
(
  SELECT JOB_ID
       , AVG(SALARY) AS SAL_AVG
    FROM HR.EMPLOYEES
   GROUP BY JOB_ID
)
SELECT A.FIRST_NAME
     , A.JOB_ID
     , A.SALARY
     , B.SAL_AVG AS DEPT_AVG
     , C.SAL_AVG AS JOB_AVG
  FROM HR.EMPLOYEES A
     , EMP_W1 B
     , EMP_W2 C
 WHERE A.EMPLOYEE_ID = 150
   AND A.DEPARTMENT_ID = B.DEPARTMENT_ID
   AND A.JOB_ID = C.JOB_ID
;

 

WITH 절 펑션 선언

WITH
   FUNCTION FN_GET_DEPT_NAME(P_DEPTNO IN NUMBER)
      RETURN VARCHAR2
   IS
      V_DNAME VARCHAR2(14);
   BEGIN
      SELECT DEPARTMENT_NAME
        INTO V_DNAME
        FROM HR.DEPARTMENTS
       WHERE DEPARTMENT_ID = P_DEPTNO;
      RETURN V_DNAME;
   END;
SELECT FIRST_NAME
     , DEPARTMENT_ID
     , FN_GET_DEPT_NAME(DEPARTMENT_ID) AS DNAME
  FROM HR.EMPLOYEES
 WHERE EMPLOYEE_ID = 150
/

FIRST_NAME	     DEPARTMENT_ID DNAME
-------------------- ------------- --------------------
Peter				80 Sales

SQL>

 

WITH 절 프로시저 선언(프로시저는 펑션내에서 호출하는 방식으로 사용 가능)

WITH
   PROCEDURE WITH_PROCEDURE(P_DNAME IN VARCHAR) IS
   BEGIN
      DBMS_OUTPUT.PUT_LINE('P_DNAME=' || P_DNAME);
   END;   
   FUNCTION FN_GET_DEPT_NAME(P_DEPTNO IN NUMBER) 
      RETURN VARCHAR2
   IS
      V_DNAME VARCHAR2(100);
   BEGIN
      SELECT DEPARTMENT_NAME
        INTO V_DNAME
        FROM HR.DEPARTMENTS
       WHERE DEPARTMENT_ID = P_DEPTNO;
-- WITH 절에 선언된 프로시저 호출 가능
      WITH_PROCEDURE(V_DNAME);
      RETURN V_DNAME;
   END;
SELECT FIRST_NAME
     , DEPARTMENT_ID
     , FN_GET_DEPT_NAME(DEPARTMENT_ID) AS DNAME
  FROM HR.EMPLOYEES
 WHERE EMPLOYEE_ID = 150
/


FIRST_NAME	     DEPARTMENT_ID DNAME
-------------------- ------------- --------------------
Peter				80 Sales

P_DNAME=Sales
SQL>

 

 

WITH 절 동작방식 차이

-- Materialize 방식(EMPLOYEES 테이블 처음 한번만 조회 후 만들어진 임시테이블 사용)

WITH EMP_W1 AS
( 
  SELECT /*+ MATERIALIZE */
        DEPARTMENT_ID
       , SUM(SALARY) AS SAL
    FROM HR.EMPLOYEES
   GROUP BY DEPARTMENT_ID
)
SELECT A.DEPARTMENT_ID
     , B.DEPARTMENT_NAME
     , A.SAL
  FROM EMP_W1 A
     , HR.DEPARTMENTS B
 WHERE A.DEPARTMENT_ID = B.DEPARTMENT_ID
UNION ALL 
SELECT A.DEPARTMENT_ID
     , B.DEPARTMENT_NAME
     , A.SAL
  FROM EMP_W1 A
     , HR.DEPARTMENTS B
 WHERE A.DEPARTMENT_ID = B.DEPARTMENT_ID
UNION ALL 
SELECT A.DEPARTMENT_ID
     , B.DEPARTMENT_NAME
     , A.SAL
  FROM EMP_W1 A
     , HR.DEPARTMENTS B
 WHERE A.DEPARTMENT_ID = B.DEPARTMENT_ID
;
 
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation				 | Name 		     | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT			 |			     |	    1 |        |       |    15 (100)|	       |     33 |00:00:00.01 |	    20 |       |       |	  |
|   1 |  TEMP TABLE TRANSFORMATION		 |			     |	    1 |        |       |	    |	       |     33 |00:00:00.01 |	    20 |       |       |	  |
|   2 |   LOAD AS SELECT (CURSOR DURATION MEMORY)| SYS_TEMP_0FD9D660E_AEA9C7 |	    1 |        |       |	    |	       |      0 |00:00:00.01 |	     7 |  1024 |  1024 |	  |
|   3 |    HASH GROUP BY			 |			     |	    1 |     11 |    77 |     4	(25)| 00:00:01 |     12 |00:00:00.01 |	     6 |  1186K|  1186K| 2298K (0)|
|   4 |     TABLE ACCESS FULL			 | EMPLOYEES		     |	    1 |    107 |   749 |     3	 (0)| 00:00:01 |    107 |00:00:00.01 |	     6 |       |       |	  |
|   5 |   UNION-ALL				 |			     |	    1 |        |       |	    |	       |     33 |00:00:00.01 |	    12 |       |       |	  |
|   6 |    MERGE JOIN				 |			     |	    1 |     10 |   420 |     5	(20)| 00:00:01 |     11 |00:00:00.01 |	     4 |       |       |	  |
|   7 |     TABLE ACCESS BY INDEX ROWID 	 | DEPARTMENTS		     |	    1 |     27 |   432 |     2	 (0)| 00:00:01 |     27 |00:00:00.01 |	     4 |       |       |	  |
|   8 |      INDEX FULL SCAN			 | DEPT_ID_PK		     |	    1 |     27 |       |     1	 (0)| 00:00:01 |     27 |00:00:00.01 |	     2 |       |       |	  |
|*  9 |     SORT JOIN				 |			     |	   27 |     11 |   286 |     3	(34)| 00:00:01 |     11 |00:00:00.01 |	     0 |  2048 |  2048 | 2048  (0)|
|  10 |      VIEW				 |			     |	    1 |     11 |   286 |     2	 (0)| 00:00:01 |     12 |00:00:00.01 |	     0 |       |       |	  |
|  11 |       TABLE ACCESS FULL 		 | SYS_TEMP_0FD9D660E_AEA9C7 |	    1 |     11 |    77 |     2	 (0)| 00:00:01 |     12 |00:00:00.01 |	     0 |       |       |	  |
|  12 |    MERGE JOIN				 |			     |	    1 |     10 |   420 |     5	(20)| 00:00:01 |     11 |00:00:00.01 |	     4 |       |       |	  |
|  13 |     TABLE ACCESS BY INDEX ROWID 	 | DEPARTMENTS		     |	    1 |     27 |   432 |     2	 (0)| 00:00:01 |     27 |00:00:00.01 |	     4 |       |       |	  |
|  14 |      INDEX FULL SCAN			 | DEPT_ID_PK		     |	    1 |     27 |       |     1	 (0)| 00:00:01 |     27 |00:00:00.01 |	     2 |       |       |	  |
|* 15 |     SORT JOIN				 |			     |	   27 |     11 |   286 |     3	(34)| 00:00:01 |     11 |00:00:00.01 |	     0 |  2048 |  2048 | 2048  (0)|
|  16 |      VIEW				 |			     |	    1 |     11 |   286 |     2	 (0)| 00:00:01 |     12 |00:00:00.01 |	     0 |       |       |	  |
|  17 |       TABLE ACCESS FULL 		 | SYS_TEMP_0FD9D660E_AEA9C7 |	    1 |     11 |    77 |     2	 (0)| 00:00:01 |     12 |00:00:00.01 |	     0 |       |       |	  |
|  18 |    MERGE JOIN				 |			     |	    1 |     10 |   420 |     5	(20)| 00:00:01 |     11 |00:00:00.01 |	     4 |       |       |	  |
|  19 |     TABLE ACCESS BY INDEX ROWID 	 | DEPARTMENTS		     |	    1 |     27 |   432 |     2	 (0)| 00:00:01 |     27 |00:00:00.01 |	     4 |       |       |	  |
|  20 |      INDEX FULL SCAN			 | DEPT_ID_PK		     |	    1 |     27 |       |     1	 (0)| 00:00:01 |     27 |00:00:00.01 |	     2 |       |       |	  |
|* 21 |     SORT JOIN				 |			     |	   27 |     11 |   286 |     3	(34)| 00:00:01 |     11 |00:00:00.01 |	     0 |  2048 |  2048 | 2048  (0)|
|  22 |      VIEW				 |			     |	    1 |     11 |   286 |     2	 (0)| 00:00:01 |     12 |00:00:00.01 |	     0 |       |       |	  |
|  23 |       TABLE ACCESS FULL 		 | SYS_TEMP_0FD9D660E_AEA9C7 |	    1 |     11 |    77 |     2	 (0)| 00:00:01 |     12 |00:00:00.01 |	     0 |       |       |	  |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

-- Inline 방식(메인 쿼리에서 EMPLOYEES 테이블 계속 조회 함)

WITH EMP_W1 AS
( 
  SELECT /*+ INLINE */
        DEPARTMENT_ID
       , SUM(SALARY) AS SAL
    FROM HR.EMPLOYEES
   GROUP BY DEPARTMENT_ID
)
SELECT A.DEPARTMENT_ID
     , B.DEPARTMENT_NAME
     , A.SAL
  FROM EMP_W1 A
     , HR.DEPARTMENTS B
 WHERE A.DEPARTMENT_ID = B.DEPARTMENT_ID
UNION ALL
SELECT A.DEPARTMENT_ID
     , B.DEPARTMENT_NAME
     , A.SAL
  FROM EMP_W1 A
     , HR.DEPARTMENTS B
 WHERE A.DEPARTMENT_ID = B.DEPARTMENT_ID
UNION ALL
SELECT A.DEPARTMENT_ID
     , B.DEPARTMENT_NAME
     , A.SAL
  FROM EMP_W1 A
     , HR.DEPARTMENTS B
 WHERE A.DEPARTMENT_ID = B.DEPARTMENT_ID
 ;

------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation		      | Name	    | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
------------------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT	      | 	    |	   1 |	      |       |    21 (100)|	      |     33 |00:00:00.01 |	   30 |       |       | 	 |
|   1 |  UNION-ALL		      | 	    |	   1 |	      |       | 	   |	      |     33 |00:00:00.01 |	   30 |       |       | 	 |
|   2 |   MERGE JOIN		      | 	    |	   1 |	   11 |   462 |     7  (29)| 00:00:01 |     11 |00:00:00.01 |	   10 |       |       | 	 |
|   3 |    TABLE ACCESS BY INDEX ROWID| DEPARTMENTS |	   1 |	   27 |   432 |     2	(0)| 00:00:01 |     27 |00:00:00.01 |	    4 |       |       | 	 |
|   4 |     INDEX FULL SCAN	      | DEPT_ID_PK  |	   1 |	   27 |       |     1	(0)| 00:00:01 |     27 |00:00:00.01 |	    2 |       |       | 	 |
|*  5 |    SORT JOIN		      | 	    |	  27 |	   11 |   286 |     5  (40)| 00:00:01 |     11 |00:00:00.01 |	    6 |  2048 |  2048 | 2048  (0)|
|   6 |     VIEW		      | 	    |	   1 |	   11 |   286 |     4  (25)| 00:00:01 |     12 |00:00:00.01 |	    6 |       |       | 	 |
|   7 |      HASH GROUP BY	      | 	    |	   1 |	   11 |    77 |     4  (25)| 00:00:01 |     12 |00:00:00.01 |	    6 |  1186K|  1186K| 2355K (0)|
|   8 |       TABLE ACCESS FULL       | EMPLOYEES   |	   1 |	  107 |   749 |     3	(0)| 00:00:01 |    107 |00:00:00.01 |	    6 |       |       | 	 |
|   9 |   MERGE JOIN		      | 	    |	   1 |	   11 |   462 |     7  (29)| 00:00:01 |     11 |00:00:00.01 |	   10 |       |       | 	 |
|  10 |    TABLE ACCESS BY INDEX ROWID| DEPARTMENTS |	   1 |	   27 |   432 |     2	(0)| 00:00:01 |     27 |00:00:00.01 |	    4 |       |       | 	 |
|  11 |     INDEX FULL SCAN	      | DEPT_ID_PK  |	   1 |	   27 |       |     1	(0)| 00:00:01 |     27 |00:00:00.01 |	    2 |       |       | 	 |
|* 12 |    SORT JOIN		      | 	    |	  27 |	   11 |   286 |     5  (40)| 00:00:01 |     11 |00:00:00.01 |	    6 |  2048 |  2048 | 2048  (0)|
|  13 |     VIEW		      | 	    |	   1 |	   11 |   286 |     4  (25)| 00:00:01 |     12 |00:00:00.01 |	    6 |       |       | 	 |
|  14 |      HASH GROUP BY	      | 	    |	   1 |	   11 |    77 |     4  (25)| 00:00:01 |     12 |00:00:00.01 |	    6 |  1186K|  1186K| 2355K (0)|
|  15 |       TABLE ACCESS FULL       | EMPLOYEES   |	   1 |	  107 |   749 |     3	(0)| 00:00:01 |    107 |00:00:00.01 |	    6 |       |       | 	 |
|  16 |   MERGE JOIN		      | 	    |	   1 |	   11 |   462 |     7  (29)| 00:00:01 |     11 |00:00:00.01 |	   10 |       |       | 	 |
|  17 |    TABLE ACCESS BY INDEX ROWID| DEPARTMENTS |	   1 |	   27 |   432 |     2	(0)| 00:00:01 |     27 |00:00:00.01 |	    4 |       |       | 	 |
|  18 |     INDEX FULL SCAN	      | DEPT_ID_PK  |	   1 |	   27 |       |     1	(0)| 00:00:01 |     27 |00:00:00.01 |	    2 |       |       | 	 |
|* 19 |    SORT JOIN		      | 	    |	  27 |	   11 |   286 |     5  (40)| 00:00:01 |     11 |00:00:00.01 |	    6 |  2048 |  2048 | 2048  (0)|
|  20 |     VIEW		      | 	    |	   1 |	   11 |   286 |     4  (25)| 00:00:01 |     12 |00:00:00.01 |	    6 |       |       | 	 |
|  21 |      HASH GROUP BY	      | 	    |	   1 |	   11 |    77 |     4  (25)| 00:00:01 |     12 |00:00:00.01 |	    6 |  1186K|  1186K| 2355K (0)|
|  22 |       TABLE ACCESS FULL       | EMPLOYEES   |	   1 |	  107 |   749 |     3	(0)| 00:00:01 |    107 |00:00:00.01 |	    6 |       |       | 	 |
------------------------------------------------------------------------------------------------------------------------------------------------------------------

댓글