Jak działa tabela Oracle DUAL?

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

SQL> select 4*5 from dual;

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

SQL>

Uważam to za bardzo dziwne. Jeśli w trybie podwójnym nie ma kolumny o nazwie 4 * 5, jak działa instrukcja select?

Dlaczego nie widzę tego samego zachowania po utworzeniu własnego podwójnego stołu?

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
źródło

Odpowiedzi:

29

Z Wikipedii :

Tabela DUAL jest specjalną tabelą jednorzędową domyślnie występującą we wszystkich instalacjach baz danych Oracle. Jest odpowiedni do użycia przy wybieraniu pseudokolumny, takiej jak SYSDATE lub USER. Tabela ma jedną kolumnę VARCHAR2 (1) o nazwie DUMMY, która ma wartość „X”.

Zatem podwójna tabela jest sposobem na wykonywanie operacji w stosunku do pustej, ale nie zerowej tabeli. Jest to przydatne, gdy nie zależy nam na tabeli, ale trzeba wykonać operacje za pomocą instrukcji select. Jeśli tabela zawiera więcej niż jeden wiersz lub kolumnę, zostanie zwróconych wiele wyników (ze względu na działanie na całym zestawie krotek podczas wykonywania operacji).

Nie należy go używać w środowisku produkcyjnym, chyba że trzeba specjalnie wywołać określone procedury za pomocą SQL.

4*5jest operacją matematyczną, podobnie jak 'Foo' łańcuch. Tak więc, podobnie jak można wybrać 4 * 5 z dowolnej tabeli, tak jak można wybrać „Foo” z dowolnej tabeli, DUAL jest sposobem na wybranie go ze znanej dobrej tabeli, która nigdy nie przyniesie wielu wyników.

Z dokumentacji (POJĘCIA):

DUAL to mała tabela w słowniku danych, do której można odwoływać się do bazy danych Oracle i programów napisanych przez użytkownika, aby zagwarantować znany wynik. Podwójna tabela jest przydatna, gdy wartość musi zostać zwrócona tylko raz, na przykład bieżąca data i godzina. Wszyscy użytkownicy bazy danych mają dostęp do DUAL.

Tabela DUAL ma jedną kolumnę o nazwie DUMMY i jeden wiersz zawierający wartość X.

I odwołanie do SQL :

DUAL to tabela tworzona automatycznie przez Oracle Database wraz ze słownikiem danych. DUAL jest w schemacie użytkownika SYS, ale jest dostępny pod nazwą DUAL dla wszystkich użytkowników. Ma jedną kolumnę, DUMMY, zdefiniowaną jako VARCHAR2 (1) i zawiera jeden wiersz o wartości X. Wybieranie z tabeli DUAL jest przydatne do obliczania stałego wyrażenia za pomocą instrukcji SELECT. Ponieważ DUAL ma tylko jeden wiersz, stała jest zwracana tylko raz. Alternatywnie możesz wybrać stałą, pseudokolumnę lub wyrażenie z dowolnej tabeli, ale wartość zostanie zwrócona tyle razy, ile jest wierszy w tabeli. Zobacz „Informacje o funkcjach SQL”, aby uzyskać wiele przykładów wybierania stałej wartości z DUAL.

Począwszy od Oracle Database 10g Release 1, logiczne operacje we / wy nie są wykonywane w tabeli DUAL podczas obliczania wyrażenia, które nie zawiera kolumny DUMMY. Ta optymalizacja jest wymieniona jako FAST DUAL w planie wykonania. Jeśli wybierzesz kolumnę DUMMY z DUAL, wówczas ta optymalizacja nie nastąpi i nastąpi logiczne we / wy.

Brian Ballsun-Stanton
źródło
5
„Nie należy go używać w środowisku produkcyjnym, chyba że trzeba specjalnie wywoływać określone procedury za pomocą SQL”. Dlaczego nie?
Nick Pierpoint
2
Nie mogę również zgodzić się, że nie należy go używać w produkcji. Dla mnie to brzmi jak mem „odciąć końce pieczeni”.
ErikE
1
Ta odpowiedź wymaga poprawy, ponieważ nie zgadza się z samym sobą. W jednym miejscu kopiuje z oficjalnych dokumentów: „Podwójny stół jest przydatny ”, aw innym zaleca: „Nie powinien być stosowany w produkcji, chyba że ...”
ypercubeᵀᴹ
18

DUAL jest tabelą zawierającą dokładnie jeden wiersz, jak pokaże następująca instrukcja SQL:

SELECT * FROM dual;

Twój dual2stół nie ma wierszy. Jeśli wstawisz jeden, zobaczysz to samo zachowanie.

4 * 5 to wyrażenie, które Oracle może ocenić bez faktycznego wykorzystania danych z tabeli. Oceni to raz dla każdego wiersza, tak jak zrobiłby to z normalnym wyrażeniem kolumny. Więc jeśli nie ma wiersza, wynik nie jest zwracany, jeśli są dwa wiersze, otrzymasz 20 razy dwa.

Hendrik Brummermann
źródło
14

dualStół „działa” prawie tak, jak wszelkie inne prace stołowe: jest to tabela, z której można wybrać rekordy.

Oznacza to na przykład, że możesz opisać tabelę. Tutaj w SQL*Plus:

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

Tak więc tabela ma jedną kolumnę o nazwie, dummyktóra jest varchar2(1).

Tabela ma z założenia jeden rekord (przynajmniej jeśli nikt się nim nie bawił):

SQL> select count(*) from dual;

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

Tak więc, aby uzyskać takie samo zachowanie, dual2jak w przypadku dual, musisz wstawić jeden rekord do podwójnego. Jeszcze lepiej, utwórz go za pomocą create table as select(ctas):

SQL> create table dual2 as select * from dual;

Teraz twoje zapytanie działa:

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

Wcześniej powiedziałem, że dual działa prawie jak każdy inny stół. Więc kiedy to nie działa jak jakikolwiek inny stół?

Zachowuje się inaczej, jeśli nie wybrano żadnej wartości z samej tabeli. Znowu, dzięki twoim zapytaniom, pozwalam Oracle je wyjaśnić ...

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

EXPLAIN PLAN ausgef³hrt.

... aby zobaczyć, w jaki sposób można uzyskać dostęp do tabeli:

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 |
-------------------------------------------------------------------

Można zauważyć, że oświadczenie robi full table accesson dual2.

Teraz to samo z 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 |
-----------------------------------------------------------------

W tym przypadku dualtabela zachowuje się inaczej: wartość dummynie jest potrzebna, więc fast dualwykonywana jest operacja, aby instancja nie odczytała rzeczywistej wartości na dysku.

René Nyffenegger
źródło
10

Nawiasem mówiąc, DUAL jest jedną z niewielu „tabel”, która działa, gdy instancja została uruchomiona, ale baza danych nie została otwarta.

Dostajesz coś takiego

ADDR     INDX   INST_ID D
-------- ------ ------- -
0C0362D4      0       1 X
Gary
źródło
9

Oprócz innych odpowiedzi, Oracle nie jest tak wybredna co do spacji w tekście SQL (przynajmniej w niektórych miejscach). Analizator składni SQL tokenizuje także w niektórych przypadkach różnice klas znaków, a nie tylko spacje.

Na przykład możesz uruchomić takie instrukcje:

SQL> wybierz * z podwójnego;

re
-
X


SQL> wybierz (1) z podwójnego;

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

SQL> wybierz-null z podwójnego;

     -ZERO
----------


SQL> wybierz-1 z podwójnego;

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

SQL> 

Możliwe jest również uruchamianie SQL bez spacji:

SQL> wybierz * z / ** / dual;

re
-
X

Mam tutaj kilka przykładów:

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

Tanel Poder

Tanel Poder
źródło
2
Ta zdolność do pomijania wielu spacji nie jest unikalna dla Oracle. Działa tak samo w SQL Server.
ErikE
8

Szybka podwójna operacja ponownie zapisuje kod w celu zapytania o x $ dual. Ponieważ ta „tabela” jest strukturą danych C w SGA, możesz przeszukiwać ją w trybie nomount.

Wiem więcej niż ty
źródło
4

Odpowiedź na pytanie jest już udzielona. Oto kilka uwag na temat celu podwójnego stołu. Podwójne mogą być użyte do oceny wyrażeń w klauzuli select. Wiele innych systemów baz danych nie potrzebuje takiej tabeli do tego celu. MS SQL Server, MySql, Posgres może ocenić następującą instrukcję

select 3+5 ;

Oracle nie może. Instrukcja select Oracle zawsze wymaga klauzuli „z”.

Niektórych funkcji nie można używać w wyrażeniach pl / sql, takich jak DUMP .

Więc

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

zgłosi wyjątek, ale

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

będzie działać.

Można go użyć do rozszerzenia zestawu wyników zapytania

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

co dało

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

lub generuj dane za pomocą wybranych zapytań, używając CONNECT BY:

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

lub rekurencyjne CTE:

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

który zwraca

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

w sqlfiddle

cud173
źródło
3

Za to, co jest warte, działa dokładnie tak samo w 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> 

Wydaje się również, że DUAL jest także strukturą pamięci w MySQL. Zwróć uwagę na różnicę w dwóch planach wyjaśniania - „bez tabel” dla DUAL w MySQL.

Co ciekawe, nie mogę wykonać DESC na dualnym MySQL, który różni się od Oracle - ale został wprowadzony specjalnie AIUI, aby umożliwić składni Oracle działanie na 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> 
Vérace
źródło
2

W bazie danych Oracle, tabela Dual jest zasadniczo używana do uzyskania wartości pseudokolumn. Zawiera następujące właściwości:

  1. Jest własnością użytkownika sys
  2. Jest dostępny dla wszystkich użytkowników
  3. Zawiera tylko jedną kolumnę o nazwie fikcyjnej z typem danych Varchar2 (1). Ta kolumna może mieć maksymalną szerokość jednego znaku.

Jeśli chcesz uzyskać więcej szczegółów, sprawdź tutaj

Vipul
źródło