Wie funktioniert die Oracle DUAL-Tabelle?


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

SQL> select 4*5 from dual;

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

SQL>

Ich finde es wirklich seltsam. Wenn es keine Spalte mit dem Namen 4 * 5 in dual gibt, wie funktioniert die select-Anweisung?

Warum sehe ich nicht dasselbe Verhalten, wenn ich meine eigene duale Tabelle erstelle?

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> 

Antworten:


29

Aus Wikipedia :

Die DUAL-Tabelle ist eine spezielle einzeilige Tabelle, die standardmäßig in allen Oracle-Datenbankinstallationen vorhanden ist. Es eignet sich zur Auswahl einer Pseudospalte wie SYSDATE oder USER. Die Tabelle enthält eine einzelne VARCHAR2 (1) -Spalte namens DUMMY mit dem Wert 'X'.

Somit ist die Doppeltabelle eine Möglichkeit, Operationen an einer leeren, aber nicht leeren Tabelle durchzuführen. Dies ist nützlich, wenn man sich nicht um die Tabelle kümmert, sondern Operationen über eine select-Anweisung ausführen muss. Wenn die Tabelle mehr als eine Zeile oder Spalte enthält, werden mehrere Ergebnisse zurückgegeben (da bei der Ausführung der Operation die gesamte Tupelmenge berücksichtigt wird).

Es sollte nicht in der Produktion verwendet werden, es sei denn, Sie müssen bestimmte Prozeduren speziell über SQL aufrufen.

4*5ist eine mathematische Operation, genau wie 'Foo' eine Zeichenfolge. So wie man 4 * 5 aus jeder Tabelle auswählen kann, so wie man 'Foo' aus jeder Tabelle auswählen kann, ist DUAL eine Möglichkeit, es aus einer bekanntermaßen guten Tabelle auszuwählen, die niemals mehrere Ergebnisse liefert.

Aus der Dokumentation (CONCEPTS):

DUAL ist eine kleine Tabelle im Datenwörterbuch, auf die Oracle Database und benutzerdefinierte Programme verweisen können, um ein bekanntes Ergebnis zu gewährleisten. Die Doppeltabelle ist nützlich, wenn ein Wert nur einmal zurückgegeben werden muss, z. B. das aktuelle Datum und die aktuelle Uhrzeit. Alle Datenbankbenutzer haben Zugriff auf DUAL.

Die DUAL-Tabelle enthält eine Spalte mit dem Namen DUMMY und eine Zeile mit dem Wert X.

Und die SQL-Referenz :

DUAL ist eine Tabelle, die von Oracle Database automatisch zusammen mit dem Datenwörterbuch erstellt wird. DUAL befindet sich im Schema des Benutzers SYS, ist jedoch für alle Benutzer unter dem Namen DUAL zugänglich. Die Spalte DUMMY ist als VARCHAR2 (1) definiert und enthält eine Zeile mit dem Wert X. Die Auswahl aus der DUAL-Tabelle ist nützlich, um mit der SELECT-Anweisung einen konstanten Ausdruck zu berechnen. Da DUAL nur eine Zeile enthält, wird die Konstante nur einmal zurückgegeben. Alternativ können Sie eine Konstante, eine Pseudospalte oder einen Ausdruck aus einer beliebigen Tabelle auswählen. Der Wert wird jedoch so oft zurückgegeben, wie Zeilen in der Tabelle vorhanden sind. Unter "Informationen zu SQL-Funktionen" finden Sie viele Beispiele für die Auswahl eines konstanten Werts aus DUAL.

Ab Oracle Database 10g Release 1 wird keine logische E / A für die DUAL-Tabelle ausgeführt, wenn ein Ausdruck berechnet wird, der die DUMMY-Spalte nicht enthält. Diese Optimierung ist im Ausführungsplan als FAST DUAL aufgeführt. Wenn Sie die Spalte DUMMY aus DUAL AUSWÄHLEN, findet diese Optimierung nicht statt und es erfolgt eine logische E / A.


5
"Es sollte nicht in der Produktion verwendet werden, es sei denn, Sie müssen bestimmte Prozeduren über SQL aufrufen." Warum nicht?
Nick Pierpoint

2
Ich kann auch nicht zustimmen, dass es nicht in der Produktion verwendet werden sollte. Das klingt für mich wie ein Mem "Schneiden Sie die Enden vom Braten ab".
ErikE

1
Diese Antwort muss verbessert werden, da sie nicht mit sich selbst übereinstimmt. An einer Stelle wird aus den offiziellen Dokumenten kopiert: "Die doppelte Tabelle ist nützlich ", und an einer anderen wird empfohlen, "Sie sollte nicht in der Produktion verwendet werden, es sei denn ..."
ypercubeᵀᴹ

18

DUAL ist eine Tabelle mit genau einer Zeile, wie die folgende SQL-Anweisung zeigt:

SELECT * FROM dual;

Ihre dual2Tabelle enthält keine Zeilen. Wenn Sie eine einfügen, sehen Sie das gleiche Verhalten.

4 * 5 ist ein Ausdruck, den Oracle auswerten kann, ohne tatsächlich Daten aus der Tabelle zu verwenden. Es wird einmal für jede Zeile ausgewertet, genau wie bei einem normalen Spaltenausdruck. Wenn also keine Zeile vorhanden ist, wird kein Ergebnis zurückgegeben. Wenn zwei Zeilen vorhanden sind, erhalten Sie die 20 zweimal.


14

Die dualTabelle "funktioniert" fast genauso wie jede andere Tabelle: Es handelt sich um eine Tabelle, aus der Sie Datensätze auswählen können.

So können Sie beispielsweise die Tabelle beschreiben. Hier in SQL*Plus:

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

Die Tabelle hat also eine Spalte mit dem Namen dummya varchar2(1).

Die Tabelle enthält standardmäßig einen Datensatz (zumindest, wenn niemand daran herumgespielt hat):

SQL> select count(*) from dual;

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

Um dasselbe Verhalten dual2wie mit dualzu erzielen, müssen Sie einen Datensatz in dual einfügen. Besser noch, erstelle es mit einem create table as select(ctas):

SQL> create table dual2 as select * from dual;

Jetzt funktioniert Ihre Abfrage:

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

Zuvor habe ich gesagt, dass Dual fast wie jeder andere Tisch funktioniert. Also, wenn es nicht funktioniert wie jede andere Tabelle?

Es verhält sich anders, wenn kein Wert aus der Tabelle selbst ausgewählt ist. Auch bei Ihren Fragen lasse ich Oracle erklären ...

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

EXPLAIN PLAN ausgef³hrt.

... um zu sehen, wie auf die Tabelle zugegriffen wird:

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

Es ist ersichtlich, dass die Anweisung a full table access ondual2 .

Nun dasselbe mit 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 |
-----------------------------------------------------------------

Hier dualverhält sich die Tabelle anders: Der Wert von dummywird nicht benötigt, daher wird eine fast dualOperation ausgeführt, damit die Instanz den tatsächlichen Wert auf der Festplatte nicht liest.


10

Übrigens ist DUAL eine der wenigen Tabellen, die funktionieren, wenn die Instanz gestartet wurde, die Datenbank jedoch nicht geöffnet wurde.

Du bekommst so etwas wie

ADDR     INDX   INST_ID D
-------- ------ ------- -
0C0362D4      0       1 X

9

Zusätzlich zu anderen Antworten ist Oracle nicht so wählerisch in Bezug auf den SQL-Text für Leerzeichen (zumindest an einigen Stellen). Der SQL-Parser wird in einigen Fällen auch durch Zeichenklassenunterschiede und nicht nur durch Leerzeichen gekennzeichnet.

Beispielsweise können Sie solche Anweisungen ausführen:

SQL> wählen Sie * aus dual;

D
-
X


SQL> wählen Sie (1) aus dual;

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

SQL> select-null from dual;

     -NULL
----------


SQL> select-1 von dual;

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

SQL> 

Es ist auch möglich, SQL ohne Leerzeichen auszuführen:

SQL> wähle * aus / ** / dual;

D
-
X

Ich habe hier noch einige Beispiele:

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

Tanel Poder


2
Diese Möglichkeit, viele Leerzeichen wegzulassen, gibt es nicht nur bei Oracle. Funktioniert genauso in SQL Server.
ErikE

8

Eine schnelle Dual-Operation schreibt Ihren Code neu, um x $ dual abzufragen. Da diese "Tabelle" eine C-Datenstruktur in der SGA ist, können Sie sie im Nomount-Modus abfragen.


4

Die Frage ist bereits beantwortet. Dies sind einige Hinweise zum Zweck der Doppeltabelle. Dual kann verwendet werden, um Ausdrücke in einer select-Klausel auszuwerten. Viele andere Datenbanksysteme benötigen für diesen Zweck keine solche Tabelle. MS SQL Server, MySQL, Posgres können die folgende Anweisung auswerten

select 3+5 ;

Oracle kann nicht. Eine Oracle Select-Anweisung benötigt immer eine "from" -Klausel.

Einige Funktionen können nicht in pl / sql-Ausdrücken wie DUMP verwendet werden .

So

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

wird aber eine ausnahme auslösen

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

wird funktionieren.

Es kann verwendet werden, um die Ergebnismenge einer Abfrage zu erweitern

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

was gab

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

oder generieren Sie Daten mit ausgewählten Abfragen, indem Sie entweder CONNECT BY:

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

oder ein rekursiver CTE:

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

was zurückkehrt

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

in sqlfiddle


3

Für das, was es wert ist, funktioniert es in MySQL genauso.

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> 

Und es scheint, dass DUAL auch in MySQL eine Art Speicherstruktur hat. Beachten Sie den Unterschied in den beiden EXPLAIN-Plänen - "Keine Tabellen verwendet" für DUAL in MySQL.

Interessanterweise kann ich mit MySQLs Dual keinen DESC durchführen, der sich von Oracle unterscheidet. Es wurde jedoch speziell AIUI eingeführt, damit die Oracle-Syntax unter MySQL funktioniert.

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

In der Oracle-Datenbank wird Dual-Tabelle grundsätzlich verwendet, um den Wert von Pseudospalten abzurufen. Es enthält folgende Eigenschaften:

  1. Es gehört dem sys-Benutzer
  2. Es steht allen Benutzern zur Verfügung
  3. Es enthält nur eine Spalte, deren Name beim Datentyp Varchar2 (1) Dummy ist. Diese Spalte darf maximal ein Zeichen breit sein.

Wenn Sie mehr Details erfahren möchten, klicken Sie hier

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.