Oracle DUAL 테이블은 어떻게 작동합니까?


32
SQL> desc dual
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 DUMMY                                              VARCHAR2(1)

SQL> select 4*5 from dual;

       4*5
----------
        20

SQL>

정말 이상하다고 생각합니다. 이중으로 4 * 5라는 열이 없으면 select 문은 어떻게 작동합니까?

또한 듀얼 테이블을 만들 때 왜 같은 동작이 나타나지 않습니까?

SQL> create table dual2(dummy varchar2(1)); 

Table created.

SQL> desc dual2
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 DUMMY                                              VARCHAR2(1)

SQL> select 4*5 from dual2;

no rows selected

SQL> 

답변:


29

에서 위키 백과 :

DUAL 테이블은 모든 Oracle 데이터베이스 설치에 기본적으로 존재하는 특수한 1 행 테이블입니다. SYSDATE 또는 USER와 같은 의사 열을 선택하는 데 사용하기에 적합합니다. 테이블에는 값이 'X'인 DUMMY라는 단일 VARCHAR2 (1) 열이 있습니다.

따라서 이중 테이블은 비어 있지만 널이 아닌 테이블에 대해 조작을 수행하는 방법입니다. 테이블에 신경 쓰지 않지만 select 문을 통해 작업을 수행해야 할 때 유용합니다. 테이블에 둘 이상의 행 또는 열이있는 경우, 조작을 수행 할 때 전체 튜플 세트에서 작동하기 때문에 여러 결과가 리턴됩니다.

SQL을 통해 특정 프로 시저를 구체적으로 호출해야하는 경우가 아니면 프로덕션 환경에서 사용해서는 안됩니다.

4*5'Foo' 문자열 과 마찬가지로 수학 연산 입니다. 따라서 어떤 테이블에서든 4 * 5를 선택할 수있는 것처럼 다른 테이블에서 'Foo'를 선택할 수있는 것처럼 DUAL은 여러 개의 결과가없는 잘 알려진 테이블에서이를 선택하는 방법입니다.

로부터 문서 (CONCEPTS) :

DUAL은 Oracle Database 및 사용자 작성 프로그램이 알려진 결과를 보장하기 위해 참조 할 수있는 데이터 사전의 작은 테이블입니다. 이중 테이블은 현재 날짜 및 시간과 같이 값을 한 번만 리턴해야하는 경우에 유용합니다. 모든 데이터베이스 사용자는 DUAL에 액세스 할 수 있습니다.

DUAL 테이블에는 DUMMY라는 열과 값 X를 포함하는 행이 있습니다.

그리고 SQL 참조 :

DUAL은 Oracle Database에서 데이터 사전과 함께 자동으로 생성 한 테이블입니다. DUAL은 SYS 사용자의 스키마에 있지만 모든 사용자가 DUAL이라는 이름으로 액세스 할 수 있습니다. 여기에는 VARCHAR2 (1)로 정의 된 하나의 열 DUMMY가 있고 값이 X 인 하나의 행이 있습니다. DUAL 테이블에서 선택하면 SELECT 문으로 상수 표현식을 계산하는 데 유용합니다. DUAL에는 행이 하나만 있으므로 상수는 한 번만 반환됩니다. 또는 테이블에서 상수, 의사 열 또는 표현식을 선택할 수 있지만 테이블에 행이있는 횟수만큼 값이 반환됩니다. DUAL에서 상수 값을 선택하는 많은 예는 "SQL 함수 정보"를 참조하십시오.

Oracle Database 10g Release 1부터는 DUMMY 열을 포함하지 않는 표현식을 계산할 때 DUAL 테이블에서 논리적 I / O가 수행되지 않습니다. 이 최적화는 실행 계획에서 FAST DUAL로 표시됩니다. DUAL에서 DUMMY 열을 선택하면이 최적화가 수행되지 않고 논리적 I / O가 발생합니다.


5
"SQL을 통해 특정 프로 시저를 구체적으로 호출해야하는 경우가 아니라면 프로덕션 환경에서 사용해서는 안됩니다."왜 그렇지 않습니까?
Nick Pierpoint

2
또한 프로덕션에 사용해서는 안된다는 데 동의하지 않습니다. 그것은 "로스트에서 끝을 자르십시오"밈처럼 들립니다.
ErikE

1
이 답변은 동의하지 않기 때문에 개선이 필요합니다. 한 곳의 공식 문서에서 그것을 복사에서 : "듀얼 표는 유용 " 다른 년에는 권장 "그것은 사용하지 말아야 하지 않는 한 ... 생산"
ypercubeᵀᴹ

18

DUAL 다음 SQL 문이 표시하는 것처럼 정확히 하나의 행이있는 테이블입니다.

SELECT * FROM dual;

귀하의 dual2테이블에 행이 없습니다. 하나를 삽입하면 동일한 동작이 나타납니다.

4 * 5는 Oracle이 실제로 테이블의 데이터를 사용하지 않고 평가할 수있는 표현식입니다. 일반 열 식에서와 마찬가지로 모든 행에 대해 한 번씩 평가합니다. 따라서 행이 없으면 결과가 반환되지 않고 두 개의 행이 있으면 20을 두 번 얻게됩니다.


14

dual표는 "작동" 거의 다른 테이블 작품 다만 방법을 : 당신이 기록을 선택할 수있는 테이블입니다.

예를 들어, 테이블을 설명 할 수 있습니다. 여기에 SQL*Plus:

SQL> set lines 50
SQL> desc dual
Name                    Null?    Typ
----------------------- -------- ----------------
DUMMY                            VARCHAR2(1)

그래서, 표라는 하나의 열이 dummy입니다 varchar2(1).

이 테이블에는 의도적으로 하나의 레코드가 있습니다 (적어도 아무도 함께 묶지 않은 경우).

SQL> select count(*) from dual;

COUNT(*)
----------
         1

따라서와 동일한 동작을 dual2수행하려면 dual하나의 레코드를 이중에 삽입해야합니다. 더 나은 방법은 create table as select(ctas)로 작성하십시오 .

SQL> create table dual2 as select * from dual;

이제 쿼리가 작동합니다.

SQL> select 4*5 from dual2;
       4*5
----------
        20

이전에는 듀얼이 다른 테이블과 거의 동일하게 작동 한다고 말했습니다 . 그래서, 그것은 다른 테이블처럼 작동하지 않는 이유는 무엇입니까?

테이블 자체에서 값을 선택하지 않으면 다르게 작동합니다. 다시 한 번, 귀하의 쿼리를 통해 오라클이 설명 하도록합니다 ...

SQL> set lines 150
SQL> explain plan for select 4*5 from dual2;

EXPLAIN PLAN ausgef³hrt.

... 테이블에 액세스하는 방법을 보려면 :

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------
Plan hash value: 3445655939

-------------------------------------------------------------------
| Id  | Operation         | Name  | Rows  | Cost (%CPU)| Time     |
-------------------------------------------------------------------
|   0 | SELECT STATEMENT  |       |     1 |     3   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| DUAL2 |     1 |     3   (0)| 00:00:01 |
-------------------------------------------------------------------

명령문이 full table accesson 임을 알 수 있습니다 dual2.

이제와 같은 것 dual:

SQL> explain plan for select 4*5 from dual;

EXPLAIN PLAN ausgef³hrt.

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
-------------------------------------------------------------------
Plan hash value: 1388734953

-----------------------------------------------------------------
| Id  | Operation        | Name | Rows  | Cost (%CPU)| Time     |
-----------------------------------------------------------------
|   0 | SELECT STATEMENT |      |     1 |     2   (0)| 00:00:01 |
|   1 |  FAST DUAL       |      |     1 |     2   (0)| 00:00:01 |
-----------------------------------------------------------------

여기에서 dual테이블이 다르게 작동합니다. 값이 dummy필요 fast dual하지 않으므로 인스턴스가 디스크의 실제 값을 읽지 않도록 조작이 실행됩니다.


10

또한 DUAL은 인스턴스가 시작되었지만 데이터베이스가 열리지 않은 경우 작동하는 몇 가지 '테이블'중 하나입니다.

당신은 같은 것을 얻습니다

ADDR     INDX   INST_ID D
-------- ------ ------- -
0C0362D4      0       1 X

9

다른 답변 외에도 Oracle은 공간 SQL 텍스트에 대해 까다 롭지 않습니다 (적어도 어떤 곳에서는). 또한 SQL 구문 분석기는 공백 만이 아니라 문자 클래스 차이로 토큰 화합니다.

예를 들어, 다음 명령문을 실행할 수 있습니다.

SQL> select * from dual;

디
-
엑스


SQL> select (1) 이중;

       (1)
----------
         1

듀얼에서 SQL> select-null;

     -없는
----------


SQL> select-1 from dual;

        -1
----------
        -1

SQL> 

공백없이 SQL을 실행할 수도 있습니다.

SQL> select * from / ** / dual;

디
-
엑스

여기에 몇 가지 예가 더 있습니다.

http://blog.tanelpoder.com/2008/01/14/can-you-write-a-working-sql-statement-without-using-any-whitespace/

타넬 파더


2
많은 공간을 생략하는이 기능은 Oracle 고유의 기능이 아닙니다. SQL Server에서 동일하게 작동합니다.
ErikE

8

빠른 이중 작업은 x $ dual을 쿼리하기 위해 코드를 다시 작성합니다. 이 "테이블"은 SGA에서 C 데이터 구조이므로 nomount 모드에서 쿼리 할 수 ​​있습니다.


4

질문은 이미 답변되었습니다. 이중 테이블의 목적에 대한 참고 사항입니다. 이중은 select 절에서 표현식을 평가하는 데 사용할 수 있습니다. 다른 많은 데이터베이스 시스템에서는 이러한 목적으로 이러한 테이블이 필요하지 않습니다. MS SQL Server, MySql, Posgres는 다음 문장을 평가할 수 있습니다.

select 3+5 ;

오라클은 할 수 없습니다. Oracle select 문에는 항상 "from"절이 필요합니다.

DUMP 와 같은 pl / sql 표현식에서는 일부 함수를 사용할 수 없습니다 .

그래서

declare
str varchar2(100);
begin
str:=dump('Hallo');
end;
/

예외를 제기하지만

declare
str varchar2(100);
begin
select dump('Hallo') into str from dual;
end;
/

작동합니다.

쿼리 결과 집합을 확장하는 데 사용할 수 있습니다.

select user_id,username from user_users
union all
select -1,'NO USER'
from dual
/

어떤

| USER_ID |     USERNAME |
|---------|--------------|
|  476267 | USER_4_E8C50 |
|      -1 |      NO USER |

또는 CONNECT BY다음 중 하나를 사용하여 선택 쿼리로 데이터를 생성하십시오 .

select level as n 
from dual
connect by level <= 5 ;

또는 재귀 CTE :

with nlist(n) as (
  select 1 from dual
  union all
  select n+1
  from nlist 
  where n<5    )
select n
from nlist
 ;

어떤 반환

| N |
|---|
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |

에서 sqlfiddle


3

가치가있는 것은 MySQL에서와 똑같은 방식으로 작동합니다.

mysql> use test;
Database changed

mysql> create table fred(billy int);
Query OK, 0 rows affected (0.79 sec)

mysql> select 4 + 5 from fred;
Empty set (0.00 sec)

mysql> select 4 + 5 as mary from fred;
Empty set (0.00 sec)

mysql> insert into fred values(1);
Query OK, 1 row affected (0.13 sec)

mysql> select 4 + 5 from fred;
+-------+
| 4 + 5 |
+-------+
|     9 |
+-------+
1 row in set (0.00 sec)

mysql> select 4 + 5 as mary from fred;
+------+
| mary |
+------+
|    9 |
+------+
1 row in set (0.00 sec)

mysql> insert into fred values(2);
Query OK, 1 row affected (0.08 sec)

mysql> select 4 + 5 from fred;
+-------+
| 4 + 5 |
+-------+
|     9 |
|     9 |
+-------+
2 rows in set (0.00 sec)

mysql> select 4 + 5 as mary from fred;
+------+
| mary |
+------+
|    9 |
|    9 |
+------+
2 rows in set (0.00 sec)

mysql> explain select 4 + 5 as mary from fred;
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | fred  | ALL  | NULL          | NULL | NULL    | NULL |    2 | NULL  |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)

mysql> 

또한 DUAL은 MySQL에서 일종의 메모리 구조 인 것으로 보입니다. MySQL의 DUAL에 대해 "사용 된 테이블 없음"이라는 두 가지 설명 계획의 차이점에 유의하십시오.

그러나 흥미롭게도 Oracle과는 다른 MySQL의 듀얼에서는 DESC를 수행 할 수 없지만 Oracle 구문이 MySQL에서 작동하도록 AIUI를 도입했습니다.

mysql> select 4 + 5 from dual;
+-------+
| 4 + 5 |
+-------+
|     9 |
+-------+
1 row in set (0.00 sec)

mysql> explain select 4 + 5 from dual;
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra          |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
|  1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | No tables used |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
1 row in set (0.00 sec)

mysql> desc dual;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'dual' at line 1
mysql> 

2

오라클 데이터베이스에서 듀얼 테이블은 기본적으로 의사 열의 값을 얻는 데 사용됩니다. 다음과 같은 속성이 있습니다.

  1. sys 사용자가 소유합니다.
  2. 모든 사용자가 사용할 수 있습니다
  3. 데이터 유형이 Varchar2 (1) 인 더미 인 하나의 열만 포함합니다.이 열의 최대 너비는 한 문자입니다.

자세한 내용을 보려면 여기를 확인 하십시오

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.