Come funziona la tabella Oracle DUAL?


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

SQL> select 4*5 from dual;

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

SQL>

Lo trovo davvero strano. Se non esiste una colonna denominata 4 * 5 in dual, come funziona l'istruzione select?

Inoltre, perché non vedo lo stesso comportamento quando creo la mia doppia tabella?

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> 

Risposte:


29

Da Wikipedia :

La tabella DUAL è una tabella speciale a una riga presente per impostazione predefinita in tutte le installazioni di database Oracle. È adatto per l'uso nella selezione di una pseudocolonna come SYSDATE o USER. La tabella ha una singola colonna VARCHAR2 (1) chiamata DUMMY che ha un valore di 'X'.

Pertanto, la tabella doppia è un modo per eseguire operazioni rispetto a ciò che equivale a una tabella vuota ma non nulla. Ciò è utile quando non ci si preoccupa della tabella, ma è necessario eseguire operazioni tramite un'istruzione select. Se la tabella avesse più di una riga o colonna, verranno restituiti più risultati (a causa dell'operare sull'intera serie di tuple durante l'esecuzione dell'operazione).

Non dovrebbe essere usato in produzione, a meno che non sia necessario invocare determinate procedure tramite SQL.

4*5è un'operazione matematica, proprio come 'Foo' una stringa. Pertanto, così come si può selezionare 4 * 5 da qualsiasi tabella, così come si può selezionare "Foo" da qualsiasi tabella, DUAL è un modo per selezionarlo da una tabella nota che non avrà mai più risultati.

Dalla documentazione (CONCEPTS):

DUAL è una piccola tabella nel dizionario dei dati a cui Oracle Database e i programmi scritti dall'utente possono fare riferimento per garantire un risultato noto. La tabella doppia è utile quando un valore deve essere restituito una sola volta, ad esempio, la data e l'ora correnti. Tutti gli utenti del database hanno accesso a DUAL.

La tabella DUAL ha una colonna chiamata DUMMY e una riga contenente il valore X.

E il riferimento SQL :

DUAL è una tabella creata automaticamente dal database Oracle insieme al dizionario dei dati. DUAL è nello schema dell'utente SYS ma è accessibile con il nome DUAL a tutti gli utenti. Ha una colonna, DUMMY, definita come VARCHAR2 (1) e contiene una riga con un valore X. La selezione dalla tabella DUAL è utile per calcolare un'espressione costante con l'istruzione SELECT. Poiché DUAL ha solo una riga, la costante viene restituita una sola volta. In alternativa, puoi selezionare una costante, una pseudocolonna o un'espressione da qualsiasi tabella, ma il valore verrà restituito tante volte quante sono le righe nella tabella. Fare riferimento a "Informazioni sulle funzioni SQL" per molti esempi di selezione di un valore costante da DUAL.

A partire da Oracle Database 10g versione 1, l'I / O logico non viene eseguito nella tabella DUAL quando si calcola un'espressione che non include la colonna DUMMY. Questa ottimizzazione è elencata come FAST DUAL nel piano di esecuzione. Se si seleziona la colonna DUMMY da DUAL, questa ottimizzazione non ha luogo e si verifica l'I / O logico.


5
"Non dovrebbe essere usato in produzione, a meno che non sia necessario invocare determinate procedure tramite SQL" Perché no?
Nick Pierpoint,

2
Inoltre, non posso essere d'accordo sul fatto che non dovrebbe essere utilizzato in produzione. A me sembra un meme "taglia le punte dell'arrosto".
ErikE

1
Questa risposta ha bisogno di miglioramenti in quanto non è d'accordo con se stessa. In un punto copia dai documenti ufficiali: "La doppia tabella è utile " e in un altro raccomanda "Non dovrebbe essere usato in produzione, a meno che ..."
ypercubeᵀᴹ

18

DUAL è una tabella con esattamente una riga come mostrerà la seguente istruzione SQL:

SELECT * FROM dual;

La tua dual2tabella non ha righe. Se ne inserisci uno, vedrai lo stesso comportamento.

4 * 5 è un'espressione che Oracle può valutare senza effettivamente utilizzare i dati della tabella. Lo valuterà una volta per ogni riga, proprio come farebbe con una normale espressione di colonna. Quindi se non ci sono righe, non viene restituito alcun risultato, se ci sono due righe, otterrai 20 due volte.


14

La dualtabella "funziona" quasi esattamente come qualsiasi altra tabella: è una tabella da cui è possibile selezionare i record.

Questo significa, ad esempio, che puoi descrivere la tabella. Qui, in SQL*Plus:

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

Quindi, la tabella ha una colonna, denominata dummyche è a varchar2(1).

La tabella ha, per progettazione, un record (almeno se nessuno ha giocherellato con esso):

SQL> select count(*) from dual;

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

Quindi, al fine di ottenere lo stesso comportamento dual2che hai con dual, devi inserire un record in doppio. Meglio ancora, crearlo con un create table as select(ctas):

SQL> create table dual2 as select * from dual;

Ora la tua query funziona:

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

In precedenza, ho detto che il doppio funziona quasi come qualsiasi altro tavolo. Quindi, quando non funziona come qualsiasi altro tavolo?

Si comporta diversamente, se non viene selezionato alcun valore dalla tabella stessa. Ancora una volta, con le tue domande, lascio che Oracle le spieghi ...

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

EXPLAIN PLAN ausgef³hrt.

... per vedere come si accede alla tabella:

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

Si può vedere che la dichiarazione fa un full table accesson dual2.

Ora, stessa cosa con 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 |
-----------------------------------------------------------------

È qui che la dualtabella si comporta diversamente: il valore di dummynon è necessario, quindi fast dualviene eseguita un'operazione, affinché l'istanza non legga il valore effettivo sul disco.


10

Per inciso, DUAL è una delle poche "tabelle" che funziona quando l'istanza è stata avviata ma il database non è stato aperto.

Ottieni qualcosa del genere

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

9

Oltre ad altre risposte, Oracle non è così esigente riguardo al testo SQL degli spazi (almeno in alcuni punti). Il parser SQL tokenizza anche in alcuni casi le differenze di classe di caratteri, non solo per gli spazi bianchi.

Ad esempio, è possibile eseguire tali istruzioni:

SQL> seleziona * da doppio;

D
-
X


SQL> seleziona (1) da dual;

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

SQL> select-null da dual;

     -NULLO
----------


SQL> select-1 da dual;

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

SQL> 

È anche possibile eseguire SQL senza spazi bianchi:

SQL> seleziona * da / ** / dual;

D
-
X

Ho altri esempi qui:

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

Tanel Poder


2
Questa capacità di omettere molti spazi non è unica per Oracle. Funziona allo stesso modo in SQL Server.
ErikE

8

Un'operazione doppia veloce riscrive il codice per eseguire una query x $ dual. Poiché questa "tabella" è una struttura di dati C nell'SGA, è possibile interrogarla in modalità nomount.


4

La domanda ha già una risposta. Queste sono alcune note allo scopo della doppia tabella. Il doppio può essere usato per valutare le espressioni in una clausola select. Molti altri sistemi di database non necessitano di tale tabella per questo scopo. MS SQL Server, MySql, Posgres possono valutare la seguente dichiarazione

select 3+5 ;

Oracle non può. Un'istruzione select Oracle ha sempre bisogno di una clausola "from".

Alcune funzioni non possono essere utilizzate nell'espressione pl / sql come DUMP .

Così

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

solleverà un'eccezione ma

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

funzionerà.

Può essere utilizzato per estendere il set di risultati di una query

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

che ha dato

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

o generare dati con query selezionate utilizzando CONNECT BY:

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

o un CTE ricorsivo:

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

che ritorna

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

in sqlfiddle


3

Per quello che vale, funziona esattamente allo stesso modo in 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> 

E sembra anche che DUAL sia una sorta di struttura della memoria anche in MySQL. Nota la differenza tra i due piani esplicativi: "nessuna tabella utilizzata" per DUAL in MySQL.

È interessante notare, tuttavia, che non posso fare un DESC sul dual di MySQL, che è diverso da Oracle - ma è stato introdotto specificamente AIUI per consentire alla sintassi Oracle di funzionare su 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

Nel database Oracle, la tabella doppia viene sostanzialmente utilizzata per ottenere il valore delle pseudo-colonne. Contiene le seguenti proprietà:

  1. È di proprietà dell'utente sys
  2. È disponibile per tutti gli utenti
  3. Contiene solo una colonna il cui nome è fittizio con il tipo di dati Varchar2 (1). Questa colonna può avere una larghezza massima di un carattere.

Se vuoi avere maggiori dettagli, controlla qui

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.