¿Cómo funciona la tabla Oracle DUAL?

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

SQL> select 4*5 from dual;

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

SQL>

Lo encuentro realmente extraño. Si no hay una columna llamada 4 * 5 en dual, ¿cómo funciona la instrucción select?

Además, ¿por qué no veo el mismo comportamiento cuando creo mi propia tabla dual?

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
fuente

Respuestas:

29

De Wikipedia :

La tabla DUAL es una tabla especial de una fila presente de forma predeterminada en todas las instalaciones de bases de datos Oracle. Es adecuado para su uso en la selección de una pseudocolumna como SYSDATE o USER. La tabla tiene una sola columna VARCHAR2 (1) llamada DUMMY que tiene un valor de 'X'.

Por lo tanto, la tabla dual es una forma de realizar operaciones contra lo que equivale a una tabla vacía pero no nula. Esto es útil cuando a uno no le importa la tabla, pero necesita realizar operaciones a través de una instrucción select. Si la tabla tuviera más de una fila o columna, se devolverían múltiples resultados (debido a la operación en todo el conjunto de tuplas al realizar la operación).

No debe usarse en producción, a menos que necesite invocar ciertos procedimientos a través de SQL.

4*5es una operación matemática, al igual 'Foo' que una cadena. Por lo tanto, así como uno puede seleccionar 4 * 5 de cualquier tabla, así como uno puede seleccionar 'Foo' de cualquier tabla, DUAL es una forma de seleccionarlo de una tabla buena conocida que nunca tendrá múltiples resultados.

De la documentación (CONCEPTOS):

DUAL es una pequeña tabla en el diccionario de datos que Oracle Database y los programas escritos por el usuario pueden consultar para garantizar un resultado conocido. La tabla dual es útil cuando un valor debe devolverse solo una vez, por ejemplo, la fecha y hora actuales. Todos los usuarios de la base de datos tienen acceso a DUAL.

La tabla DUAL tiene una columna llamada DUMMY y una fila que contiene el valor X.

Y la referencia SQL :

DUAL es una tabla creada automáticamente por Oracle Database junto con el diccionario de datos. DUAL está en el esquema del usuario SYS pero es accesible por el nombre DUAL para todos los usuarios. Tiene una columna, DUMMY, definida como VARCHAR2 (1), y contiene una fila con un valor X. Seleccionar de la tabla DUAL es útil para calcular una expresión constante con la instrucción SELECT. Como DUAL solo tiene una fila, la constante se devuelve solo una vez. Alternativamente, puede seleccionar una constante, pseudocolumna o expresión de cualquier tabla, pero el valor se devolverá tantas veces como haya filas en la tabla. Consulte "Acerca de las funciones de SQL" para ver muchos ejemplos de selección de un valor constante de DUAL.

A partir de Oracle Database 10g Release 1, la E / S lógica no se realiza en la tabla DUAL cuando se calcula una expresión que no incluye la columna DUMMY. Esta optimización aparece como FAST DUAL en el plan de ejecución. Si SELECCIONA la columna DUMMY de DUAL, entonces esta optimización no tiene lugar y se produce una E / S lógica.

Brian Ballsun-Stanton
fuente
55
"No debe usarse en producción, a menos que necesite invocar ciertos procedimientos a través de SQL" ¿Por qué no?
Nick Pierpoint
2
Tampoco puedo estar de acuerdo con que no debería usarse en la producción. Para mí, eso suena como un meme "corta los extremos del asado".
ErikE
1
Esta respuesta necesita mejora ya que no está de acuerdo consigo misma. En un lugar copia de los documentos oficiales: "La tabla dual es útil " y en otro recomienda "No debe usarse en producción, a menos que ..."
ypercubeᵀᴹ
18

DUAL es una tabla con exactamente una fila como se mostrará en la siguiente instrucción SQL:

SELECT * FROM dual;

Tu dual2mesa no tiene filas. Si inserta uno, verá el mismo comportamiento.

4 * 5 es una expresión que Oracle puede evaluar sin usar los datos de la tabla. Lo evaluará una vez para cada fila, al igual que lo haría con una expresión de columna normal. Entonces, si no hay una fila, no se devuelve ningún resultado, si hay dos filas, obtendrá el 20 dos veces.

Hendrik Brummermann
fuente
14

La dualtabla "funciona" casi como funciona cualquier otra tabla: es una tabla de la que puede seleccionar registros.

Esto significa, por ejemplo, que puede describir la tabla. Aquí, en SQL*Plus:

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

Entonces, la tabla tiene una columna, llamada dummycual es a varchar2(1).

La tabla tiene, por diseño, un registro (al menos si nadie jugueteó con ella):

SQL> select count(*) from dual;

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

Entonces, para obtener el mismo comportamiento con el dual2que tiene dual, debe insertar un registro en dual. Mejor aún, create table as selectcréelo con un (ctas):

SQL> create table dual2 as select * from dual;

Ahora, su consulta funciona:

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

Anteriormente, dije que dual casi funciona como cualquier otra tabla. Entonces, ¿ cuándo no funciona como cualquier otra mesa?

Se comporta de manera diferente si no se selecciona ningún valor de la tabla en sí. Nuevamente, con sus consultas, dejo que Oracle las explique ...

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

EXPLAIN PLAN ausgef³hrt.

... para ver cómo se accede a la tabla:

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

Se puede ver que la declaración hace un full table accessencendido dual2.

Ahora, lo mismo 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 |
-----------------------------------------------------------------

Aquí es donde la dualtabla se comporta de manera diferente: el valor de dummyno es necesario, por lo fast dualque se ejecuta una operación para que la instancia no lea el valor real en el disco.

René Nyffenegger
fuente
10

Por cierto, DUAL es una de las pocas 'tablas' que funciona cuando se inicia la instancia pero la base de datos no se ha abierto.

Obtienes algo como

ADDR     INDX   INST_ID D
-------- ------ ------- -
0C0362D4      0       1 X
Gary
fuente
9

Además de otras respuestas, Oracle no es tan exigente con los espacios de texto SQL (al menos en algunos lugares). El analizador SQL también tokeniza por diferencias de clase de caracteres en algunos casos, no solo por espacios en blanco.

Por ejemplo, puede ejecutar tales declaraciones:

SQL> seleccione * de dual;

re
-
X


SQL> seleccione (1) de dual;

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

SQL> select-null from dual;

     -NULO
----------


SQL> select-1 desde dual;

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

SQL> 

También es posible ejecutar SQL sin ningún espacio en blanco:

SQL> seleccione * de / ** / dual;

re
-
X

Tengo algunos ejemplos más aquí:

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

Tanel Poder

Tanel Poder
fuente
2
Esta capacidad de omitir muchos espacios no es exclusiva de Oracle. Funciona igual en SQL Server.
ErikE
8

Una operación dual rápida reescribe su código para consultar x $ dual. Debido a que esta "tabla" es una estructura de datos C en el SGA, puede consultarla en modo nomount.

sé más que tú
fuente
4

La pregunta ya está respondida. Estas son algunas notas sobre el propósito de la tabla dual. Dual se puede usar para evaluar expresiones en una cláusula select. Muchos otros sistemas de bases de datos no necesitan dicha tabla para este propósito. MS SQL Server, MySql, Posgres pueden evaluar la siguiente declaración

select 3+5 ;

Oracle no puede. Una instrucción select de Oracle siempre necesita una cláusula "from".

Algunas funciones no se pueden usar en expresiones pl / sql como DUMP .

Asi que

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

planteará una excepción pero

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

trabajará.

Se puede usar para extender el conjunto de resultados de una consulta

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

que dio

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

o generar datos con consultas seleccionadas usando CONNECT BY:

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

o un CTE recursivo:

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

que vuelve

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

en sqlfiddle

milagro173
fuente
3

Por lo que vale, funciona exactamente de la misma manera en 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> 

Y también parece que DUAL es algún tipo de estructura de memoria en MySQL también. Tenga en cuenta la diferencia en los dos planes explicativos: "no se utilizan tablas" para DUAL en MySQL.

Curiosamente, sin embargo, no puedo hacer un DESC en el dual de MySQL, que es diferente a Oracle, pero se introdujo específicamente AIUI para permitir que la sintaxis de Oracle funcione en 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
fuente
2

En la base de datos Oracle, la tabla dual se usa básicamente para obtener el valor de las pseudocolumnas. Contiene las siguientes propiedades:

  1. Es propiedad del usuario sys
  2. Está disponible para todos los usuarios.
  3. Contiene solo una columna cuyo nombre es ficticio con el tipo de datos Varchar2 (1). Esta columna puede tener un ancho máximo de un carácter.

Si desea obtener más detalles, marque aquí

Vipul
fuente