Как работает таблица Oracle DUAL?


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

SQL> select 4*5 from dual;

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

SQL>

Я нахожу это действительно странным. Если нет столбца с именем 4 * 5 в двойном, как работает оператор выбора?

Кроме того, почему я не вижу того же поведения, когда я создаю свою двойную таблицу?

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. Он подходит для использования при выборе псевдостолбца, такого как SYSDATE или USER. В таблице есть один столбец VARCHAR2 (1) с именем DUMMY, который имеет значение «X».

Таким образом, двойная таблица - это способ выполнения операций с пустой таблицей, но не с нулевой таблицей. Это полезно, когда никому нет дела до таблицы, но нужно выполнять операции с помощью оператора select. Если в таблице более одной строки или столбца, будут возвращены несколько результатов (из-за работы над всем набором кортежей при выполнении операции.)

Его не следует использовать в производственной среде, если только вам специально не нужно вызывать определенные процедуры через SQL.

4*5это математическая операция, так же как 'Foo' и строка. Таким образом, точно так же, как можно выбрать 4 * 5 из любой таблицы, точно так же, как можно выбрать «Foo» из любой таблицы, DUAL - это способ выбрать его из заведомо хорошей таблицы, которая никогда не будет иметь несколько результатов.

Из документации (КОНЦЕПЦИИ):

DUAL - это небольшая таблица в словаре данных, на которую Oracle Database и пользовательские программы могут ссылаться, чтобы гарантировать известный результат. Двойная таблица полезна, когда значение должно быть возвращено только один раз, например, текущая дата и время. Все пользователи базы данных имеют доступ к DUAL.

Таблица DUAL имеет один столбец с именем DUMMY и одну строку, содержащую значение X.

И ссылка на SQL :

DUAL - это таблица, автоматически создаваемая Oracle Database вместе со словарем данных. DUAL находится в схеме пользователя SYS, но доступен под именем DUAL для всех пользователей. Он имеет один столбец DUMMY, определенный как VARCHAR2 (1), и содержит одну строку со значением X. Выбор из таблицы DUAL полезен для вычисления константного выражения с помощью оператора SELECT. Поскольку DUAL имеет только одну строку, константа возвращается только один раз. В качестве альтернативы вы можете выбрать константу, псевдостолбец или выражение из любой таблицы, но значение будет возвращено столько раз, сколько строк в таблице. Обратитесь к разделу «О функциях SQL», чтобы найти множество примеров выбора постоянного значения из DUAL.

Начиная с Oracle Database 10g Release 1, логический ввод-вывод не выполняется для таблицы DUAL при вычислении выражения, не содержащего столбец DUMMY. Эта оптимизация указана как БЫСТРЫЙ ДВОЙНОЙ в плане выполнения. Если вы ВЫБИРАЕТЕ столбец DUMMY из DUAL, то эта оптимизация не происходит, и происходит логический ввод-вывод.


5
«Его не следует использовать в производстве, если только вам специально не нужно вызывать определенные процедуры через SQL». Почему бы и нет?
Ник Пирпойнт,

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

Ранее я говорил, что dual почти работает как любой другой стол. Итак, когда он не работает, как любой другой стол?

Он ведет себя по-другому, если не выбрано значение из самой таблицы. Опять же, с вашими запросами, я позволю Oracle объяснить их ...

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 accessна 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;

D
-
Икс


SQL> select (1) из двойного;

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

SQL> select-null from dual;

     -ЗНАЧЕНИЕ NULL
----------


SQL> select-1 из двойного;

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

SQL> 

Также возможно запустить SQL без пробелов:

SQL> select * from / ** / dual;

D
-
Икс

У меня есть еще несколько примеров здесь:

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. Поскольку эта «таблица» является структурой данных C в SGA, вы можете запросить ее в режиме nomount.


4

На вопрос уже дан ответ. Вот некоторые примечания к цели двойной таблицы. Двойной можно использовать для оценки выражений в предложении выбора. Многие другие системы баз данных не нуждаются в такой таблице для этой цели. MS SQL Server, MySql, Posgres может оценить следующее утверждение

select 3+5 ;

Оракул не может. Оператор выбора Oracle всегда нуждается в предложении "from".

Некоторые функции не могут быть использованы в выражении pl / sql, как DUMP .

Так

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. Обратите внимание на разницу в двух планах объяснения - «таблицы не используются» для DUAL в MySQL.

Интересно, однако, что я не могу сделать DESC для MySQL dual, который отличается от Oracle - но он был введен специально для AIUI, чтобы позволить синтаксису Oracle работать на MySQL.

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

В базе данных oracle двойная таблица в основном используется для получения значения псевдоколонок. Содержит следующие свойства:

  1. Он принадлежит пользователю sys
  2. Это доступно для всех пользователей
  3. Он содержит только один столбец с именем dummy с типом данных Varchar2 (1). Максимальная ширина этого столбца может составлять один символ.

Если вы хотите получить более подробную информацию, проверьте здесь

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.