Як працює таблиця 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. Він підходить для використання при виборі псевдоколонки типу 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 має лише один рядок, константа повертається лише один раз. Крім того, ви можете вибрати константу, псевдоколонку або вираз з будь-якої таблиці, але значення буде повернуто стільки разів, скільки є рядків у таблиці. Для багатьох прикладів вибору постійного значення з DUAL див. "Про функції SQL".

Починаючи з бази даних Oracle 10g, випуск 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яким - avarchar2(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

Раніше я говорив, що дуал майже працює, як і будь-який інший стіл. Отже, коли це не працює, як будь-який інший стіл?

Він поводиться по-різному, якщо не вибрано значення з самої таблиці. Знову з вашими запитами я дозволяю 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 * з подвійного;

D
-
Х


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

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

SQL> select-null з подвійного;

     -НУЛЬ
----------


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

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

SQL> 

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

SQL> виберіть * з / ** / подвійний;

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, ви можете запитувати її в номінальному режимі.


4

На питання вже відповіли. Це кілька приміток до мети подвійної таблиці. Подвійний може використовуватися для оцінки виразів у виділеному пункті. Багато інших систем баз даних не потребують такої таблиці для цієї мети. MS SQL Server, MySql, Posgres можуть оцінити наступне твердження

select 3+5 ;

Oracle не може. Оператор вибору 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, який відрізняється від 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 таблиця Dual в основному використовується для отримання значення псевдо колонок. Він містить такі властивості:

  1. Він належить користувачеві sys
  2. Він доступний для всіх користувачів
  3. Він містить лише один стовпець, назва якого є манекеном з типом даних Varchar2 (1). Цей стовпець може мати максимальну ширину одного символу.

Якщо ви хочете отримати більш детальну інформацію, перевірте тут

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.