SQL> desc dual
Name Null? Type
----------------------------------------- -------- ----------------------------
DUMMY VARCHAR2(1)
SQL> select 4*5 from dual;
4*5
----------
20
SQL>
Ich finde es wirklich seltsam. Wie funktioniert die select-Anweisung, wenn es keine Spalte mit dem Namen 4 * 5 in dual gibt?
Warum sehe ich nicht dasselbe Verhalten, wenn ich meine eigene Doppeltabelle 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>
Von 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 duale Tabelle eine Möglichkeit, Operationen für eine leere, aber nicht nullte Tabelle auszufü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 (aufgrund der Operation über den gesamten Satz von Tupeln bei der Ausführung der Operation).
Es sollte nicht in der Produktion verwendet werden, es sei denn, Sie müssen bestimmte Prozeduren speziell über SQL aufrufen.
4*5
ist eine mathematische Operation, genau wie 'Foo'
ist 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 haben wird.
Aus dem Dokumentation (KONZEPTE):
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 zusammen mit dem Datenwörterbuch automatisch erstellt wird. DUAL befindet sich im Schema des Benutzers SYS, ist jedoch für alle Benutzer unter dem Namen DUAL zugänglich. Es hat eine Spalte, DUMMY, die als VARCHAR2 (1) definiert ist, und enthält eine Zeile mit dem Wert X. Die Auswahl aus der DUAL-Tabelle ist nützlich, um einen konstanten Ausdruck mit der SELECT-Anweisung zu berechnen. Da DUAL nur eine Zeile hat, 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 werden keine logischen E/A-Vorgänge für die DUAL-Tabelle ausgeführt, wenn ein Ausdruck berechnet wird, der die DUMMY-Spalte nicht enthält. Diese Optimierung wird 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.
DUAL
ist eine Tabelle mit genau einer Zeile, wie die folgende SQL-Anweisung zeigt:
SELECT * FROM dual;
Ihre dual2
Tabelle hat keine Zeilen. Wenn Sie eine einfügen, sehen Sie dasselbe 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.
Die dual
-Tabelle "funktioniert" fast genau wie jede andere Tabelle: Es ist 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 enthält also eine Spalte mit dem Namen dummy
, die eine varchar2(1)
ist.
Der Tisch hat von Natur aus einen Datensatz (zumindest wenn niemand damit herumgespielt hat):
SQL> select count(*) from dual;
COUNT(*)
----------
1
Um mit dual2
Das gleiche Verhalten wie mit dual
zu erzielen, müssen Sie einen Datensatz in dual einfügen. Besser noch, erstellen Sie 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
Vorhin habe ich gesagt, dass dual fast wie jede andere Tabelle funktioniert. Also, wann funktioniert es nicht wie jede andere Tabelle?
Es verhält sich anders, wenn kein Wert aus der Tabelle selbst ausgewählt ist. Wieder mit Ihren Fragen lasse ich Oracle erklären sie ...
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 einen full table access
Für dual2
Ausführt.
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 verhält sich die Tabelle dual
anders: Der Wert von dummy
wird nicht benötigt, daher wird eine Operation fast dual
Ausgeführt, damit die Instanz den tatsächlichen Wert nicht liest auf der Festplatte.
DUAL ist übrigens 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
Zusätzlich zu anderen Antworten ist Oracle nicht so wählerisch in Bezug auf den Leerzeichen-SQL-Text (zumindest an einigen Stellen). Der SQL-Parser wird in einigen Fällen auch durch Zeichenklassenunterschiede gekennzeichnet, nicht nur durch Leerzeichen.
Sie können beispielsweise folgende 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> wähle-1 aus dual; -1 ---------- -1 SQL>
Es ist auch möglich, SQL ohne Leerzeichen auszuführen:
SQL> wählen Sie * aus/**/dual; D - X
Ich habe hier noch einige Beispiele:
Tanel Poder
Eine schnelle Doppeloperation 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.
Die Frage ist bereits beantwortet. Dies sind einige Anmerkungen zum Zweck der Doppeltabelle. Dual kann verwendet werden, um Ausdrücke in einer select-Klausel auszuwerten. Viele andere Datenbanksysteme benötigen zu diesem Zweck keine solche Tabelle. MS SQL Server, MySql, Posgres kann die folgende Anweisung auswerten
select 3+5 ;
Oracle kann nicht. Eine Oracle-Select-Anweisung benötigt immer eine "from" -Klausel.
Einige Funktionen wie DUMP können im pl/sql-Ausdruck nicht verwendet werden.
Damit
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 mit 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
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 auch, dass DUAL auch in MySQL eine Art Speicherstruktur ist. Beachten Sie den Unterschied zwischen den beiden Erklärungsplänen - "Keine Tabellen verwendet" für DUAL in MySQL.
Interessanterweise kann ich jedoch kein DESC für MySQL Dual ausführen, das sich von Oracle unterscheidet. Es wurde jedoch speziell für 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>
In der Oracle-Datenbank wird die Dual-Tabelle im Wesentlichen verwendet, um den Wert von Pseudospalten abzurufen. Es enthält folgende Eigenschaften:
Wenn Sie mehr Details erhalten möchten, überprüfen Sie hier