제5장 SQL 질의

내용 목차

5.1. SELECT
5.2. 조인
5.2.1. 조인 조건
5.2.2. 동등 조인
5.2.3. 자체 조인
5.2.4. 내부 조인
5.2.5. 외부 조인
5.2.6. 안티 조인
5.2.7. 세미 조인
5.3. 부질의
5.4. 집합 연산자
5.5. 계층 질의
5.5.1. 계층 질의 연산자
5.5.2. 계층 질의의 조건식
5.5.3. 계층 질의의 실행 방식
5.6. 병렬 질의
5.7. 듀얼 테이블

본 장에서는 SELECT에 대해 자세히 설명한다.

SELECT 구문은 하나 이상의 테이블, 뷰로부터 원하는 데이터를 조회한다.

SELECT의 세부 내용은 다음과 같다.

조인(Join)은 두 개 또는 여러 개의 테이블이나 뷰로부터 로우를 결합하는 질의이다. Tibero에서는 FROM 절에 다수의 테이블이 있을 때 조인을 실행한다.

질의의 SELECT 절에서 조인 테이블에 속하는 컬럼을 선택할 수 있다. 만일 조인될 테이블 중에 같은 이름의 컬럼이 2개 이상이 있다면 테이블 이름을 함께 명시해 모호함을 없애야 한다.

대부분의 조인 질의는 서로 다른 두 테이블의 컬럼을 비교하는 WHERE 절의 조건을 포함한다. 이런 조건을 조인 조건 (Join Condition)이라고 한다.

조인을 실행하기 위해서 각 테이블의 로우를 하나씩 가져와 조인 조건이 TRUE로 결정되는 경우에만 결합한다. 조인 조건에 포함되는 컬럼이 반드시 SELECT절에 포함될 필요는 없다.

세 개 이상의 테이블을 조인할 때는 우선 두 개의 테이블과 그 두 테이블의 컬럼에 대응 되는 조인 조건을 이용해서 조인을 한다. 그 후에, 그 두 테이블의 조인 결과의 컬럼과 세 번째 조인할 테이블의 컬럼에 해당하는 조인 조건으로 조인하여 새로운 결과를 만든다.

Tibero는 이러한 과정을 하나의 결과가 나올 때까지 반복한다. 최적화기(Optimizer)는 조인 조건과 테이블에 대한 인덱스와 통계 정보를 사용해 테이블 간의 조인 순서를 정한다. WHERE 절에 조인 조건 이외에 테이블에 하나에 대한 조건도 있을 수 있는데, 이러한 조건은 조인 질의로 반환되는 로우를 더욱 한정한다.

카티션 프로덕트

조인 질의에서 테이블에 대한 조인 조건이 없을 경우 카티션 프로덕트(Cartesian Products)를 반환한다. 카티션 프로덕트는 테이블의 한 로우가 다른 테이블의 모든 로우와 결합되는 것을 말한다.

예를 들어 100개의 로우를 가지는 두 개의 테이블의 카티션 프로덕트는 100 * 100 = 10,000로우이다. 카티션 프로덕트는 이렇게 결과가 너무 많기 때문에 거의 사용되지 않는다. 특별히 카티션 프로덕트가 필요한 경우가 아니라면, 항상 조인 조건을 포함해야 한다. 만일 3개 이상의 테이블을 조인 할 때 그 중 2개의 테이블에 대한 조인 조건이 없었다면, 최적화기는 되도록 카티션 프로덕트가 생기지 않도록 조인순서를 정할 것이다.

외부 조인(Outer Join)은 일반 조인을 확장한 결과를 출력한다. 외부 조인은 조인 조건을 만족하는 로우뿐만 아니라, 한 테이블의 어떤 로우에 대해 반대편 테이블의 모든 로우가 조인 조건을 만족하지 못하는 경우에도 그 로우를 출력한다.

외부 조인은 왼쪽 외부 조인, 오른쪽 외부 조인, 완전 외부 조인이 있다.

여러 테이블 간의 외부 조인을 수행하는 질의에서 하나의 테이블은 오직 다른 하나의 테이블에 대해서만 NULL을 제공하는 테이블의 역할을 할 수 있다. 따라서, 테이블 A와 B에 대한 조건과 테이블 B와 C에 대한 조건에서 모두 B의 컬럼 쪽에 (+) 연산자를 적용할 수는 없다.

외부 조인 연산자 (+)에는 FROM 절에 외부 조인을 명시할 경우에 다음과 같은 규칙과 제약 조건이 있다.

  • FROM 절에 조인이 있는 질의 블록에는 외부 조인을 사용할 수 없다.

  • (+) 연산자는 WHERE 절에만 올 수 있고, 테이블이나 뷰의 컬럼에만 적용할 수 있다.

  • 테이블 A와 B의 조인 조건이 여러 개 있을 경우에는 '(+)' 연산자를 모든 조건에 사용해야 한다. 그렇지 않은 경우에는 아무런 경고나 에러 메시지 없이 일반 조인과 같이 취급한다.

  • (+) 연산자를 외부 테이블과 내부 테이블에 모두 사용할 경우에는 일반 조인과 같이 취급한다.

  • (+) 연산자는 컬럼에만 적용될 수 있고, 일반 연산식에는 적용될 수 없다. 단, 연산식 내의 컬럼에 '(+)' 연산자를 적용할 수는 있다.

  • (+) 연산자를 포함하는 조건은 WHERE 절의 다른 조건과 OR 연산자를 통해 묶일 수 없다.

  • (+) 연산자가 적용된 컬럼을 IN 연산자를 이용해 비교하는 조건을 사용할 수 없다.

  • (+) 연산자가 적용된 컬럼을 부질의의 결과와 비교할 수 없다.

  • 테이블 A와 B의 외부 조인의 조건 중에 B의 컬럼을 상수와 비교하는 조건이 있다면, '(+)' 연산자를 B의 컬럼에 적용해야 한다. 그렇지 않으면, 일반 조인과 같이 취급한다.

질의를 사용해서 어떤 문제를 해결하고자 할 때 단계를 나누어서 수행하면 좀 더 쉽게 문제를 풀 수 있는 경우가 있다.

예를 들어 Peter라는 사람이 속해있는 부서에서 일하는 사람 모두를 구하고자 할 때 먼저 Peter의 부서를 구하는 질의를 작성한 다음, 그 질의의 결과를 이용해 최종 답을 얻는 형태로 단계를 나눈 질의를 생각해 볼 수 있다. 이처럼 하나의 질의가 내부에 또 다른 질의를 포함하고 있을 경우 이 내부에 포함된 질의를 부질의(Subquery)라고 한다.

부질의는 질의가 사용된 위치에 따라 다음과 같이 두 가지 형태로 나눌 수 있다.

부질의 종류설명
인라인 뷰부질의가 부모 질의의 FROM 절에서 사용되었을 경우 이런 부질의를 보통 인라인(Inline) 뷰라고 부른다.
중첩된 부질의부 질의가 부모 질의의 SELECT 리스트 또는 WHERE 절 등에서 사용되었을 경우 이런 부질의를 중첩된(Nested) 부질의 또는 부질의라고 부른다.

부질의는 다음과 같은 경우에 종종 사용된다.

  • INSERT 문을 통해 삽입할 로우의 값을 결정할 때

  • CREATE TABLE을 통해 테이블을 생성함과 동시에 테이블의 내용을 채울 때

  • CREATE VIEW 문을 통해 뷰가 질의하는 로우의 집합을 정의할 때

  • UPDATE 문에서 UPDATE할 값을 결정할 때

  • SELECT, UPDATE, DELETE 문에서 WHERE 절, HAVING 절, START WITH 절과 같은 조건을 명시할 때

  • 테이블처럼 사용하고 싶은 로우의 집합을 정의할 때(SELECT의 FROM 절 또는 INSERT, UPDATE, DELETE에서 테이블을 명시할 수 있는 자리에 사용할 수 있다.)

참고

부질의는 내부에 다른 부질의를 포함할 수 있으며, Tibero에서는 부질의가 다른 부질의를 포함할 수 있는 단계에 대해 제한을 두지 않는다.

다음은 부질의와 컬럼 참조에 대한 설명이다.

부질의의 컬럼을 참조할 때의 규칙은 다음과 같다.

  • 서로 관련된 부질의 내에서 부모 질의의 FROM 절의 테이블의 컬럼을 참조할 때 자신의 FROM 절의 테이블의 컬럼과 동일한 이름을 가지고 있는 컬럼을 참조하고자 하는 경우에는 컬럼 이름 앞에 부모 질의의 테이블 이름을 붙여 주어야 한다.

  • 부모 질의의 컬럼을 참조할 때 위로 올라가는 단계에 대한 제한은 없다. 서로 관련된 부질의는 부모 질의의 각각의 로우를 처리할 때 매번 일일이 별도로 수행된다.

  • 컬럼 이름에 대한 모호함이 발생하지 않는 한, 부질의에서 명시하는 (테이블 이름을 앞에 붙이지 않은) 컬럼 이름은 자신의 FROM 절의 테이블에서부터 시작해서 자신의 부모, 부모의 부모 순으로 컬럼 이름을 찾아본다.

서로 관련된 부질의는 하위 단계에서 구하고자 하는 값이 상위 단계의 각각의 로우에 따라 별도로 결정되어야 하는 경우에 사용된다.

다음과 같은 경우를 가정해 보자.

  • 자신의 부서의 평균 연봉보다 많은 연봉을 받는 사원의 리스트를 구하는 질의가 있다.

  • 이때, 하위 단계에서 계산하고자 하는 값은 각 사원에 대해서 그 사원이 근무하고 있는 부서의 평균 연봉이 된다.

  • 또한, 상위 단계에서는 하위 단계에서 구한 평균 연봉을 현재 사원의 연봉과 비교하게 된다.

이러한 경우 평균 연봉을 각 사원에 대해 매번 구해야 하므로 이럴 경우 서로 관련된 부질의를 구사해서 문제를 해결할 수 있다.

다음은 스칼라(scalar) 부질의에 대한 설명이다. 자세한 내용은 “3.3.6. 부질의 연산식”을 참고한다.

집합 연산자는 두 개의 질의를 하나로 결합하는 데 사용된다. 집합 연산자에 의해 결합된 질의의 select_list에 명시된 연산식의 개수는 동일해야 하고 대응되는 연산식은 같은 데이터 타입 그룹에 속해야 한다.

다음은 집합 연산자의 우선순위에 대한 설명이다.

우선순위집합 연산자설명
1INTERSECT

두 개의 질의 결과 양쪽 모두에 존재하는 로우를 결과로 반환한다.

(A ∩ B)

2UNION두 개의 질의의 결과에서 중복된 로우를 제거한 후 결과를 반환한다. (A ∪ B)
UNION ALL두 개의 질의의 결과에서 중복된 로우를 제거시키지 않고 모든 결과를 반환한다. (A + B)
MINUS앞의 질의 결과에서 뒤의 질의 결과를 뺀 결과를 반환한다. (A - B)
EXCEPTMINUS 집합 연산자와 동일하게 동작한다. (A - B)

두 개 이상의 질의가 집합 연산자에 의해 결합되면, 다음과 같은 규칙이 적용된다.

  • 왼쪽에서 오른쪽 순서로 질의를 수행한다.

  • 괄호를 사용하여 쿼리의 수행 순서를 조정할 수 있다.

집합 연산자는 다음과 같은 제약조건이 있다.

  • select_list가 BLOB, CLOB 타입의 연산식을 가질 경우 집합 연산자를 사용할 수 없다.

  • UNION, INTERSECT, MINUS, EXCEPT 연산자의 경우 LONG 타입의 컬럼이 허용되지 않는다.

  • 먼저 명시된 질의의 select_list에 나오는 연산식에 별칭이 명시되어야만 order_by_clause에서 참조할 수 있다.

  • for_update_clause를 명시할 수 없다.

대응되는 연산식이 동일한 데이터 타입의 그룹이 아니면 암시적인 형 변환은 허용되지 않으며, 동일한 데이터 타입의 그룹이면 다음과 같은 형 변환이 일어난다.

  • 데이터 타입의 그룹이 숫자이면, 결과는 NUMBER 타입이다.

  • 데이터 타입의 그룹이 문자이면, 다음의 규칙에 의해 결과의 데이터 타입이 결정된다.

    • 양쪽이 CHAR 타입이면, 결과는 CHAR 타입이다.

    • 하나 또는 양쪽 모두 VARCHAR2 타입이면, 결과는 VARCHAR2 타입이다.

계층 질의(Hierarchical Query)란 테이블에 포함된 로우 사이에 상하 계층 관계가 성립된 경우 그 상관 관계에 따라 로우를 출력하는 질의이다.

하나의 대상 테이블에 계층 관계는 하나 이상 정의할 수 있으며, 계층 질의는 하나의 테이블 또는 조인된 둘 이상의 테이블에 대해서도 가능하다.

계층 질의를 위하여 SELECT 문장 내에 START WITH … CONNECT BY 절을 이용한다.

PRIOR

CONNECT BY 절에는 다른 조건식에서는 포함되지 않는 특별한 연산자가 사용되는데, 로우 간의 상하 관계를 나타내기 위한 PRIOR 연산자이다.

PRIOR 연산자가 포함된 조건식은 다음과 같은 형식을 갖는다.

PRIOR expr = expr
expr = PRIOR expr

PRIOR 쪽의 연산식의 결과 값을 갖는 로우가 반대 쪽의 연산식의 결과 값을 갖는 로우의 부모가 된다.

예를 들어 두 개의 컬럼 EMPNO와 MGRNO를 포함하는 테이블 EMP에 대하여 다음의 조건식을 이용하여 계층 질의를 수행한다면, 특정 (부모) 로우의 EMPNO 컬럼 값과 같은 MGRNO 컬럼 값을 갖는 모든 로우는, EMPNO 컬럼 값을 갖는 로우의 자식 로우가 된다.

PRIOR EMPNO = MGRNO

다음의 테이블 EMP2 내의 로우 중에서 EMPNO 컬럼 값이 27인 (부모) 로우에 대하여 EMPNO 컬럼 값이 35, 42인 로우가 자식 로우가 된다. 두 컬럼 모두 MGRNO 컬럼 값이 27이기 때문이다.

     EMPNO ENAME        ADDR                 SALARY      MGRNO
---------- ------------ ---------------- ---------- ----------
        35 John         Houston               30000         27
        54 Alicia       Castle                25000         24
        27 Ramesh       Humble                38000         12
        69 James        Houston               35000         24
        42 Allen        Brooklyn              29000         27
        87 Ward         Humble                28500         35
        24 Martin       Spring                30000         12
        12 Clark        Palo Alto             45000          5

CONNECT BY 절의 조건식은 여러 단순 조건식이 연결된 복합 조건식이 될 수 있다. 하지만, PRIOR 연산자를 포함한 단순 조건식은 반드시 하나만 포함되어야 하며, 0개 또는 2개 이상이 포함된 경우에는 에러를 반환한다. CONNECT BY 절의 조건식은 부질의를 포함할 수 없다.

CONNECT_BY_ROOT

계층 질의에서만 사용되는 또 다른 특수 연산자로 CONNECT_BY_ROOT 연산자가 있다.

CONNECT_BY_ROOT 연산자를 사용하면 데이터베이스는 루트 로우의 데이터를 이용하여 컬럼 값을 반환한다.

다음은 CONNECT_BY_ROOT 연산자를 사용한 예이다.

SQL> SELECT ENAME, CONNECT_BY_ROOT ENAME MANAGER,
            SYS_CONNECT_BY_PATH(ENAME, '-') PATH
     FROM EMP2
     WHERE LEVEL > 1
       CONNECT BY PRIOR EMPNO = MGRNO
       START WITH ENAME = 'Clark';

ENAME           MANAGER         PATH
--------------- --------------- -----------------------
Martin          Clark           -Clark-Martin
James           Clark           -Clark-Martin-James
Alicia          Clark           -Clark-Martin-Alicia
Ramesh          Clark           -Clark-Ramesh
Allen           Clark           -Clark-Ramesh-Allen
JohnClark       Clark           -Ramesh-John
Ward            Clark           -Clark-Ramesh-John-Ward

7 rows selected.

계층 질의는 재귀적(Recursive)으로 실행된다.

먼저 하나의 루트 로우에 대해 모든 자식 로우를 검색한다. 그 다음 각 자식 로우의 자식 로우를 다시 검색한다. 이러한 방법으로 다시는 자식 로우가 발견되지 않을 때까지 계속 진행한다. 만약 무한 루프가 되면 에러를 반환한다.

계층 질의의 결과를 출력하는 순서는 깊이 우선(Depth-First) 순서를 따른다.

다음의 그림은 테이블 EMP2의 계층 질의 결과로 구성된 계층 관계의 한 예이며, 원 안의 값은 EMPNO 컬럼의 값이다. 이때, 로우의 출력 순서는 12, 27, 35, 87, 42, 24, 54, 69이다.


계층 트리의 각 로우는 레벨 값을 갖는다. 루트 로우의 레벨 값은 1이며 자식 로우로 내려가면서 1씩 증가한다. 따라서, 위의 [그림 5.1]에서 EMPNO = 12인 로우는 레벨이 1이며, EMPNO = 27, 24인 로우는 레벨이 2, EMPNO = 35, 42, 54, 69인 로우는 레벨이 3, EMPNO = 87인 로우는 레벨이 4다.

레벨 값은 의사 컬럼인 LEVEL 컬럼의 값으로 출력할 수 있다.

다음은 START WITH 절을 이용하지 않고 계층 질의를 실행하는 SELECT 문의 예이다. 본 예제에서는 모든 로우를 루트 로우로 하여 하부 로우를 출력한다.

SQL> SELECT EMPNO, ENAME, ADDR, MGRNO
     FROM EMP2
       CONNECT BY PRIOR EMPNO = MGRNO;

     EMPNO ENAME        ADDR                  MGRNO
---------- ------------ ---------------- ----------
        12 Clark        Palo Alto                 5
        27 Ramesh       Humble                   12
        35 John         Houston                  27
        87 Ward         Humble                   35
        42 Allen        Brooklyn                 27
        24 Martin       Spring                   12
        54 Alicia       Castle                   24
        69 James        Houston                  24
        27 Ramesh       Humble                   12
        35 John         Houston                  27
        87 Ward         Humble                   35
        42 Allen        Brooklyn                 27
        24 Martin       Spring                   12
        54 Alicia       Castle                   24
        69 James        Houston                  24
        54 Alicia       Castle                   24
        69 James        Houston                  24
        35 John         Houston                  27
        87 Ward         Humble                   35
        42 Allen        Brooklyn                 27
        87 Ward         Humble                   35

21 rows selected.

다음은 START WITH 절을 이용하여 계층 질의를 실행하는 SELECT 문의 예이다. 본 예제에서는 EMPNO = 12인 조건식을 만족하는 하나의 루트 로우에 대해서만 하부 로우를 검색한다.

SQL> SELECT EMPNO, ENAME, ADDR, MGRNO
     FROM EMP2
       START WITH EMPNO = 12
       CONNECT BY PRIOR EMPNO = MGRNO;

     EMPNO ENAME        ADDR                  MGRNO
---------- ------------ ---------------- ----------
        12 Clark        Palo Alto                 5
        27 Ramesh       Humble                   12
        35 John         Houston                  27
        87 Ward         Humble                   35
        42 Allen        Brooklyn                 27
        24 Martin       Spring                   12
        54 Alicia       Castle                   24
        69 James        Houston                  24

8 rows selected.

다음은 WHERE 절을 포함하여 계층 질의를 실행하는 SELECT 문의 예이다. 본 예제에서는 EMPNO = 27인 로우가 WHERE 절 때문에 제거되었으나, 그 하부 로우는 모두 그대로 출력된다.

SQL> SELECT EMPNO, ENAME, ADDR, MGRNO
     FROM EMP2
       WHERE ENAME != ’Ramesh’
       START WITH EMPNO = 12
       CONNECT BY PRIOR EMPNO = MGRNO;

     EMPNO ENAME        ADDR                  MGRNO
---------- ------------ ---------------- ----------
        12 Clark        Palo Alto                 5
        35 John         Houston                  27
        87 Ward         Humble                   35
        42 Allen        Brooklyn                 27
        24 Martin       Spring                   12
        54 Alicia       Castle                   24
        69 James        Houston                  24

7 rows selected.

다음은 LEVEL 컬럼을 포함하여 계층 질의를 실행하는 SELECT 문의 예이다.

SQL> SELECT EMPNO, ENAME, ADDR, MGRNO, LEVEL
     FROM EMP2
       START WITH EMPNO = 12
       CONNECT BY PRIOR EMPNO = MGRNO;

     EMPNO ENAME        ADDR                  MGRNO      LEVEL
---------- ------------ ---------------- ---------- ----------
        12 Clark        Palo Alto                 5          1
        27 Ramesh       Humble                   12          2
        35 John         Houston                  27          3
        87 Ward         Humble                   35          4
        42 Allen        Brooklyn                 27          3
        24 Martin       Spring                   12          2
        54 Alicia       Castle                   24          3
        69 James        Houston                  24          3

8 rows selected.

병렬 질의란 하나의 SQL 문장을 여러 워킹 스레드를 사용하여 처리하는 것을 말한다. 대용량 테이블을 스캔할 때 여러 워킹 스레드가 테이블의 영역을 나눠서 처리하면 워킹 스레드 하나를 사용했을 때보다 빠르게 작업을 실행할 수 있다.

병렬 질의는 OLTP(Online transaction processing) 환경 보다는 주로 데이터 웨어하우스(Data warehouse)와 같은 대용량 데이터를 다루는 환경에서 주로 사용된다.

다음은 병렬 질의를 사용하는 예이다.

SELECT /*+ PARALLEL (4) */ DEPTNO, AVG(SAL) FROM EMP GROUP BY DEPTNO;

위의 예에서처럼 병렬 질의를 사용하기 위해서는 PARALLEL 힌트를 사용하면 된다. 'PARALLEL (4)'라고 명시한 부분의 숫자 4는 병렬 질의 처리에서 사용할 워킹 스레드의 개수를 나타내며 보통 DOP(Degree of parallelism)라고 한다. 즉 4개의 워킹 스레드를 사용해 해당 질의를 처리하도록 지시한다.

이와 같이 병렬 질의 실행이 지시되면 Tibero 서버는 유휴 상태의 워킹 스레드를 사용자가 지정한 DOP 개수만큼 확보하려 할 것이다.

현재 사용할 수 있는 워킹 스레드가 힌트에 지정된 개수보다 부족하다면 확보할 수 있는 워킹 스레드만을 사용해 병렬 질의를 실행한다. 만약 유휴 상태의 워킹 스레드가 없어서, DOP가 1이 되면 병렬 질의는 진행되지 않으며, 일반 질의처럼 처리된다. 이러한 상황을 별도의 에러 메시지를 통해 알려주지는 않는다.

Tibero가 병렬 질의로 실행할 수 있는 연산은 다음과 같다.

  • TABLE FULL SCAN

  • INDEX FAST FULL SCAN

  • HASH JOIN

  • NESTED LOOP JOIN

  • MERGE JOIN

  • SET 연산

  • GROUP BY

  • ORDER BY

  • 집계 함수

Tibero는 병렬 질의를 실행하기 위해 실행 계획을 생성한다.

다음은 병렬 질의를 실행하기 위해 실행 계획을 생성한 예이다.

SQL> SET AUTOT TRACE EXPLAIN
SQL> SELECT EMPNO, ENAME, SAL FROM EMP ORDER BY SAL;
SQL ID: 451
Plan Hash Value: 2848347407

Explain Plan
--------------------------------------------------------------------------------
1  ORDER BY (SORT)
2    TABLE ACCESS (FULL): EMP


SQL> SELECT /*+ PARALLEL (4) */ EMPNO, ENAME, SAL FROM EMP ORDER BY SAL;
SQL ID: 449
Plan Hash Value: 979088785

Explain Plan
--------------------------------------------------------------------------------
1  PE MANAGER
2    PE SEND QC (ORDER)
3      ORDER BY (SORT)
4        PE RECV
5          PE SEND (RANGE)
6            PE BLOCK ITERATOR
7              TABLE ACCESS (FULL): EMP

위의 예를 보면, PARALLEL 힌트를 사용한 병렬 질의의 실행 계획에 기존에는 없던 새로운 연산 노드가 추가가 된 것을 확인 할 수 있다. 이때 새로 추가된 노드는 병렬 질의 실행에 필요한 작업을 하게 된다.

PE RECV, PE SEND 노드가 추가된 경우에는 Tibero는 병렬 질의를 실행하기 위해 2-set 모델을 사용한다. 이 경우 실제 사용하는 워킹 스레드의 개수는 DOP의 2배가 되며 2개의 set 중에서 한 곳의 워킹 스레드는 consumer의 역할을, 다른 set의 워킹 스레드는 producer의 역할을 하게 된다. 이렇게 2-set 모델을 사용하는 이유는 두 연산 노드를 동시에 병렬로 실행하여 파이프라이닝(Pipelining) 효과를 보기 위해서이다.

듀얼 테이블(DUAL Table)은 VARCHAR(1) 타입의 하나의 컬럼 더미(Dummy)와 문자열 'X'를 포함하는 하나의 로우를 포함하는 테이블이다.

듀얼 테이블의 특성은 다음과 같다.

  • SYS 사용자뿐만 아니라 모든 사용자가 듀얼 테이블을 사용할 수 있다.

  • 삽입, 삭제, 갱신 연산이 허용되지 않으며, 테이블 자체를 변경하거나 제거할 수 없다.

  • 테이블의 내용과 상관없는 연산식의 계산에 사용할 수 있다.

  • 하나의 로우만을 포함하기 때문에 항상 연산식의 결과는 하나다.

다음은 듀얼 테이블을 사용하는 예이다.

SQL> SELECT SIN(3.141592654 / 2.0) FROM DUAL;

SIN(3.141592654/2.0)
--------------------
                   1

1 row selected.