Comment fonctionne la table Oracle DUAL?

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

SQL> select 4*5 from dual;

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

SQL>

Je trouve ça vraiment étrange. S'il n'y a pas de colonne nommée 4 * 5 en double, comment fonctionne l'instruction select?

Aussi, pourquoi ne vois-je pas le même comportement lorsque je crée ma propre table double?

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

Réponses:

29

De Wikipédia :

La table DUAL est une table spéciale à une ligne présente par défaut dans toutes les installations de base de données Oracle. Il peut être utilisé pour sélectionner une pseudocolonne telle que SYSDATE ou USER. La table a une seule colonne VARCHAR2 (1) appelée DUMMY qui a une valeur de «X».

Ainsi, la table double est un moyen d'effectuer des opérations sur ce qui équivaut à une table vide mais non nulle. Ceci est utile lorsque l'on ne se soucie pas de la table, mais doit effectuer des opérations via une instruction select. Si la table avait plus d'une ligne ou colonne, plusieurs résultats seraient retournés (en raison de l'opération sur l'ensemble des tuples lors de l'exécution de l'opération).

Il ne doit pas être utilisé en production, sauf si vous devez spécifiquement invoquer certaines procédures via SQL.

4*5est une opération mathématique, tout comme 'Foo' une chaîne. Ainsi, tout comme on peut sélectionner 4 * 5 dans n'importe quelle table, tout comme on peut sélectionner 'Foo' dans n'importe quelle table, DUAL est un moyen de le sélectionner à partir d'une table connue qui n'aura jamais plusieurs résultats.

De la documentation (CONCEPTS):

DUAL est une petite table dans le dictionnaire de données que la base de données Oracle et les programmes écrits par l'utilisateur peuvent référencer pour garantir un résultat connu. La table double est utile lorsqu'une valeur ne doit être retournée qu'une seule fois, par exemple, la date et l'heure actuelles. Tous les utilisateurs de la base de données ont accès à DUAL.

La table DUAL a une colonne appelée DUMMY et une ligne contenant la valeur X.

Et la référence SQL :

DUAL est une table créée automatiquement par Oracle Database avec le dictionnaire de données. DUAL est dans le schéma de l'utilisateur SYS mais est accessible par le nom DUAL à tous les utilisateurs. Il a une colonne, DUMMY, définie pour être VARCHAR2 (1), et contient une ligne avec une valeur X. La sélection dans la table DUAL est utile pour calculer une expression constante avec l'instruction SELECT. Parce que DUAL n'a qu'une seule ligne, la constante n'est renvoyée qu'une seule fois. Vous pouvez également sélectionner une constante, une pseudocolonne ou une expression dans n'importe quelle table, mais la valeur sera renvoyée autant de fois qu'il y a de lignes dans la table. Reportez-vous à "A propos des fonctions SQL" pour de nombreux exemples de sélection d'une valeur constante dans DUAL.

À partir d'Oracle Database 10g version 1, les E / S logiques ne sont pas effectuées sur la table DUAL lors du calcul d'une expression qui n'inclut pas la colonne DUMMY. Cette optimisation est répertoriée comme FAST DUAL dans le plan d'exécution. Si vous sélectionnez la colonne DUMMY dans DUAL, cette optimisation n'a pas lieu et des E / S logiques se produisent.

Brian Ballsun-Stanton
la source
5
"Il ne doit pas être utilisé en production, sauf si vous devez spécifiquement invoquer certaines procédures via SQL" Pourquoi pas?
Nick Pierpoint
2
Je ne peux pas non plus convenir qu'il ne devrait pas être utilisé en production. Pour moi, cela ressemble à un mème «couper les extrémités du rôti».
ErikE
1
Cette réponse doit être améliorée car elle est en désaccord avec elle-même. En un seul endroit, il copie des documents officiels: "La double table est utile " et dans un autre, il recommande "Il ne devrait pas être utilisé dans la production, sauf ..."
ypercube
18

DUAL est une table avec exactement une ligne, comme l'indique l'instruction SQL suivante:

SELECT * FROM dual;

Votre dual2table ne contient aucune ligne. Si vous en insérez un, vous verrez le même comportement.

4 * 5 est une expression qu'Oracle peut évaluer sans réellement utiliser les données de la table. Il l'évaluera une fois pour chaque ligne, comme il le ferait avec une expression de colonne normale. Donc, s'il n'y a pas de ligne, aucun résultat n'est renvoyé, s'il y a deux lignes, vous obtiendrez les 20 deux fois.

Hendrik Brummermann
la source
14

La dualtable "fonctionne" presque comme n'importe quelle autre table: c'est une table dans laquelle vous pouvez sélectionner des enregistrements.

Cela signifie, par exemple, que vous pouvez décrire le tableau. Ici, dansSQL*Plus :

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

Ainsi, la table a une colonne, nommée dummy qui est un varchar2(1).

La table a, par conception, un enregistrement (du moins si personne ne l'a manipulé):

SQL> select count(*) from dual;

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

Donc, pour obtenir le même comportement que celui dual2que vous avez avec dual, vous devez insérer un enregistrement dans le double. Mieux encore, créez-le avec uncreate table as select (ctas):

SQL> create table dual2 as select * from dual;

Maintenant, votre requête fonctionne:

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

Un peu plus tôt, je l' ai dit que la double presque fonctionne comme n'importe quelle autre table. Alors, quand ça ne marche pas comme n'importe quelle autre table?

Il se comporte différemment si aucune valeur de la table elle-même n'est sélectionnée. Encore une fois, avec vos questions, je laisse Oracle expliquer ...

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

EXPLAIN PLAN ausgef³hrt.

... afin de voir comment accéder à la table:

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

On peut voir que la déclaration fait un full table access on dual2.

Maintenant, même chose avec 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 |
-----------------------------------------------------------------

C'est là que la dualtable se comporte différemment: la valeur de dummyn'est pas nécessaire, donc une fast dualopération est exécutée, afin que l'instance ne lise pas la valeur réelle sur le disque.

René Nyffenegger
la source
10

Soit dit en passant, DUAL est l'une des rares «tables» qui fonctionne lorsque l'instance a été démarrée mais que la base de données n'a pas été ouverte.

Vous obtenez quelque chose comme

ADDR     INDX   INST_ID D
-------- ------ ------- -
0C0362D4      0       1 X
Gary
la source
9

En plus d'autres réponses, Oracle n'est pas aussi pointilleux sur le texte SQL des espaces (à certains endroits au moins). L'analyseur SQL tokenize également par les différences de classe de caractères dans certains cas, pas seulement par les espaces.

Par exemple, vous pouvez exécuter de telles instructions:

SQL> sélectionnez * parmi dual;

ré
-
X


SQL> sélectionnez (1) parmi dual;

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

SQL> select-null de dual;

     -NUL
----------


SQL> select-1 de dual;

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

SQL> 

Il est également possible d'exécuter SQL sans aucun espace:

SQL> sélectionnez * dans / ** / dual;

ré
-
X

J'ai d'autres exemples ici:

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

Tanel Poder

Tanel Poder
la source
2
Cette possibilité d'omettre de nombreux espaces n'est pas unique à Oracle. Fonctionne de la même manière dans SQL Server.
ErikE
8

Une double opération rapide réécrit votre code pour interroger x $ dual. Étant donné que cette "table" est une structure de données C dans le SGA, vous pouvez l'interroger en mode nomount.

J'en sais plus que toi
la source
4

La question est déjà répondue. Ce sont quelques notes sur l'objectif du tableau double. Dual peut être utilisé pour évaluer des expressions dans une clause select. De nombreux autres systèmes de base de données n'ont pas besoin d'une telle table à cet effet. MS SQL Server, MySql, Posgres peuvent évaluer l'instruction suivante

select 3+5 ;

Oracle ne peut pas. Une instruction Oracle select a toujours besoin d'une clause "from".

Certaines fonctions ne peuvent pas être utilisées dans une expression pl / sql comme DUMP .

Alors

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

soulèvera une exception mais

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

marchera.

Il peut être utilisé pour étendre le jeu de résultats d'une requête

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

ce qui a donné

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

ou générer des données avec des requêtes sélectionnées en utilisant CONNECT BY:

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

ou un CTE récursif:

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

qui revient

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

à sqlfiddle

miracle173
la source
3

Pour ce que ça vaut, cela fonctionne exactement de la même manière dans 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> 

Et il apparaît également que DUAL est également une sorte de structure de mémoire dans MySQL. Notez la différence entre les deux plans d'explication - "aucune table utilisée" pour DUAL dans MySQL.

Cependant, je ne peux pas faire de DESC sur le dual de MySQL, qui est différent d'Oracle - mais il a été introduit spécifiquement AIUI pour permettre à la syntaxe Oracle de fonctionner sur 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
la source
2

Dans la base de données Oracle, la table double est essentiellement utilisée pour obtenir la valeur des pseudo-colonnes. Il contient les propriétés suivantes:

  1. Il appartient à l'utilisateur sys
  2. Il est disponible pour tous les utilisateurs
  3. Il ne contient qu'une seule colonne dont le nom est factice avec le type de données Varchar2 (1). Cette colonne peut avoir une largeur maximale d'un caractère.

Si vous souhaitez obtenir plus de détails, cochez ici

Vipul
la source