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?
De plus, 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>
De Wikipedia :
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 renvoyé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*5
est une opération mathématique, tout comme 'Foo'
est 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 un petit tableau du dictionnaire de données auquel Oracle Database et les programmes écrits par l'utilisateur peuvent faire référence 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 le 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.
DUAL
est une table avec exactement une ligne comme l'indique l'instruction SQL suivante:
SELECT * FROM dual;
Votre dual2
la table n'a pas de lignes. 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.
La table dual
"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, dans SQL*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 une 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 avec dual2
Qu'avec dual
, vous devez insérer un enregistrement dans dual. Mieux encore, créez-le avec un create 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
Plus tôt, j'ai dit que dual presque fonctionne comme n'importe quelle autre table. Alors, quand cela ne fonctionne-t-il 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 requêtes, je laisse Oracle expliquer les ...
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 l'instruction fait un full table access
Sur 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 table dual
se comporte différemment: la valeur de dummy
n'est pas nécessaire, donc une opération fast dual
Est exécutée, afin que l'instance ne lise pas la valeur réelle sur le disque.
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
En plus d'autres réponses, Oracle n'est pas aussi pointilleux sur les espaces texte SQL (à 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 double; D - X SQL> sélectionnez (1) parmi double; (1) ---------- 1 SQL> select-null from dual; -NULL ---------- SQL> sélectionnez-1 parmi les doubles; -1 ---------- -1 SQL>
Il est également possible d'exécuter SQL sans aucun espace:
SQL> sélectionnez * parmi/**/dual; D - X
J'ai d'autres exemples ici:
Tanel Poder
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.
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 l'expression pl/sql comme DUMP .
Donc
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 à l'aide de 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 |
dans sqlfiddle
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 semble également que DUAL soit é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>
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:
Si vous souhaitez obtenir plus de détails, cochez ici