it-swarm.dev

Jak działa tabela Oracle DUAL?

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 też nie widzę tego samego zachowania podczas tworzenia 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> 
32
Lazer

From Wikipedia :

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 zawiera pojedynczą 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ływać określone procedury za pomocą SQL.

4*5 jest operacją matematyczną, podobnie jak 'Foo' jest ciągiem. 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 wybrania go ze znanej dobrej tabeli, która nigdy nie będzie miała wielu wyników.

Z dokumentacja (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.

A SQL Reference :

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.

29

DUAL to tabela z dokładnie jednym wierszem, jak pokaże następująca instrukcja SQL:

SELECT * FROM dual;

Twój dual2 tabela 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.

18

Tabela dual „działa” prawie tak jak każdy inny stół: jest to tabela, z której można wybierać 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 dummy, któ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 z dual2 Jak 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 prawie działa jak każdy inny stół. Więc kiedy czy to nie działa jak jakikolwiek inny stół?

Zachowuje się inaczej, jeśli nie wybrano żadnej wartości z samej tabeli. Ponownie, z twoimi zapytaniami, pozwalam Oracle wyjaśnić je ...

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 instrukcja wykonuje full table access Na 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 tabela dual zachowuje się inaczej: wartość dummy nie jest potrzebna, dlatego wykonywana jest operacja fast dual, Aby instancja nie odczytała rzeczywistej wartości na dysku.

14

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

Oprócz innych odpowiedzi Oracle nie jest tak wybredny w kwestii spacji tekstu SQL (przynajmniej w niektórych miejscach). Parser SQL tokenizuje także w niektórych przypadkach różnice klas znaków, a nie tylko białe spacje.

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

 SQL> wybierz * z podwójnego; 
 
 D 
 - 
 X 
 
 
 SQL> wybierz (1) z podwójnego; 
 
 (1) 
 ---------- 
 1 
 
 SQL> select-null z dual; 
 
 -NULL 
 ---------- 
 
 
 SQL> wybierz-1 z podwójnego; 
 
 -1 
 ---------- 
 -1 
 
 SQL> 
 

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

 SQL> wybierz * z/**/dual; 
 
 D 
 - 
 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

9
Tanel Poder

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.

8

Odpowiedź na pytanie jest już udzielona. Oto kilka uwag dotyczących 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 |

in sqlfiddle

4
miracle173

Za to, co jest warte, działa dokładnie w taki sam sposób 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> 
3
Vérace

W bazie danych Oracle tabela Dual służy zasadniczo do uzyskiwania 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

2
Vipul