Как работает таблица 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> 
Lazer
источник

Ответы:

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
Gary
источник
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

miracle173
источник
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> 
Verace
источник
2

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

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

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

Vipul
источник