¿Por qué tengo que seleccionar de la tabla dual?

15

Esto funciona en los principales sistemas de gestión de bases de datos de relaciones con mayor probabilidad de aparecer en StackOverflow / dba.stackexchange, siendo SQL Server, MySQL, PostgreSQL y SQLite (WebSQL) .

select 'abc' abc, 1 def;

No funciona en Oracle. ¿Por qué necesitamos seleccionar DUAL en Oracle? ¿El estándar ISO / ANSI para SQL requiere una cláusula FROM para las instrucciones SELECT ?


Editar:

Según Bacon Bitla respuesta, parece ser requerido por el estándar SQL.

Entonces, en realidad, porque el nombre DUAL es un nombre inapropiado, si tuviera que crear una tabla y nombrarla ATOM o ONE, por ejemplo create table one (atom int);... select 'abc' abc, 1 def FROM one;- ¿Hay una penalización de rendimiento en comparación con SELECT .. FROM DUAL?

孔夫子
fuente
Creo que DB2 tampoco puede hacer un selectsin un from. DB2 tiene una tabla ficticia similar llamada SYSIBM.SYSDUMMY1 . También es probable que ya lo sepas, pero cuando no se accede realmente aselect 'A' from dual la dualtabla , lo que responde a la pregunta en tu edición (que mereció una nueva pregunta por cierto).
Jack dice que intente topanswers.xyz
1
No , no funciona en "todos" los DBMS. Hay varios DBMS que no permiten un SELECT sin un FROM. El manual responde a su pregunta sobre el rendimiento: docs.oracle.com/cd/E11882_01/server.112/e26088/…
a_horse_with_no_name
3
@JackDouglas: Tienes razón. DB2 requiere una FROMcláusula. Fuera de mi cabeza: Informix, Firebird y Apache Derby también lo requieren.
a_horse_with_no_name
1
DB2 requiere una cláusula FROM, pero una alternativa es usar una declaración como values ('abc', 1). Por supuesto, puede también seleccionar de tal declaración:select abc from ( values ('abc',1) ) as t(abc,def)
Lennart

Respuestas:

30

Estrictamente, sí, la FROMcláusula de una SELECTdeclaración no es opcional. La sintaxis para SQL-99 detalla el SELECTenunciado básico , y la FROMcláusula no tiene corchetes alrededor. Eso indica que el estándar lo considera no opcional:

SELECT [ DISTINCT | ALL ]
{Column expression [ AS name ]} [ ,... ] | *
FROM <Table reference> [ {,<Table reference>} ... ]
[ WHERE search condition ]
[ GROUP BY Columns [ HAVING condition ] ]
[ORDER BY {col_name | expr | position} [ASC | DESC],...]                                     
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
[PROCEDURE procedure_name(argument_list)]
[INTO OUTFILE 'file_name' export_options |
 INTO DUMPFILE 'file_name' |
 INTO var_name [, var_name]]
[FOR UPDATE | LOCK IN SHARE MODE]

En el uso real, los programadores y los DBA a menudo encuentran útil hacer otras cosas además de manipular datos en tablas o manipular tablas y estructuras de datos. Este tipo de cosas está más allá del alcance del estándar SQL, que se ocupa más de las características de los datos que de los detalles básicos de las implementaciones específicas. Ya sea que queramos ejecutar SELECT getdate()o SELECT 1o SELECT DB_NAME()(o lo que prefiera su dialecto), en realidad no queremos datos de una tabla.

Oracle elige resolver la discrepancia estándar y de implementación utilizando una tabla ficticia con la siguiente definición efectiva:

CREATE TABLE DUAL (
  DUMMY CHAR(1)
  )

INSERT INTO DUAL (DUMMY) VALUES ('X')

Otros RDBMS esencialmente suponen que se usa una tabla ficticia si no FROMse especifica ninguna .

La historia de la tabla DUAL está en Wikipedia:

La tabla DUAL fue creada por Charles Weiss de Oracle Corporation para proporcionar una tabla para unirse en vistas internas:

Creé la tabla DUAL como un objeto subyacente en el Diccionario de Datos Oracle. Nunca se pensó para verse, sino que se usó dentro de una vista que se esperaba consultar. La idea era que pudieras unirte a la tabla DUAL y crear dos filas en el resultado para cada fila de tu tabla. Luego, al usar GROUP BY, la unión resultante podría resumirse para mostrar la cantidad de almacenamiento para la extensión DATA y para la extensión o extensiones INDEX. El nombre, DUAL, parecía apto para el proceso de crear un par de filas a partir de una sola.

La tabla DUAL original tenía dos filas (de ahí su nombre), pero posteriormente solo tenía una fila.

Pedacitos de tocino
fuente
3
+1 y bienvenido a dba.se. Esta es una excelente respuesta con un poco de historia fascinante. Espero que pueda alentarse a quedarse y contribuir más :)
Jack dice que intente topanswers.xyz
44
Una vez tuve horas de diversión sin fin cuando un desarrollador insertó algunas filas más en dual. Rompió muchas cosas :) ¡Tardó un tiempo en localizar al culpable!
Philᵀᴹ
8

La ventaja duales que el optimizador comprende dualuna tabla especial de una fila y una columna (con varchar2el tipo de datos): cuando la usa en consultas, utiliza este conocimiento al desarrollar el plan.

¿Por qué necesitamos seleccionar dualen Oracle?

También puede seleccionar desde dualo desde sus propias tablas, puede hacerlo si lo desea.

Para mí, me quedaré dualporque sé que dualexiste. Sé que tiene al menos 1 y como máximo 1 fila. Sé que el optimizador lo sabe todo dualy hace lo más eficiente para mí. El optimizador entiende que duales una tabla mágica y especial de 1 fila. Se detuvo en el select *porque debe haber una fila allí. Así es como funciona.

DevYudh
fuente
"Sé que tiene al menos 1 y como máximo 1 fila". Bueno, un idiota (o un idiota) con privilegios de DBA puede modificarDUAL . ¡Ten cuidado!
Nick Chammas
bueno si eso te pasa a ti. revocar todos los privilegios excepto CREAR SESIÓN de esta persona Alguien. y que pasa si alguien cae accidentalmente?
DevYudh
puede crearlo utilizando el almacenamiento de la tabla dual dual (dummy varchar2 (1)) (inicial 1) o la tabla flashback dual antes de soltar
DevYudh
Bueno, es una ventaja usar DUAL en comparación con seleccionar la expresión de cualquier otra tabla existente, pero no explica cuál es la ventaja de tener DUAL como alternativa para no tener que tener FROM, como en PostgreSQL o SQLServer
Danubian Sailor
@Lukasz Lech en Oracle no hay SELECT sin FROM para #MSSQL Serv: no hay necesidad de una tabla dual en SQL Server. pero si transfirió su código de Oracle a SQL Serv, puede crear dual usando este script CREATE TABLE DUAL (DUMMY VARCHAR (1)) GO INSERT INTO DUAL (DUMMY) VALUES ('X') GO pero, no veo ninguno razón para usar / crear tabla dual en el servidor sql. y también MSSQL Serv y PostGRE SQL no requieren una tabla
ficticia
1

Las otras dos respuestas proporcionan buenos antecedentes para mi respuesta.

En las bases de datos Oracle, es tradicional y confiable. Fallará en otras bases de datos que no tienen una DUALtabla. No es necesario que lo use DUAL, pero le recomendaría que lo haga.

Las bases de datos que cumplan con los estándares requerirán una FROMcláusula que especifique al menos una referencia de tabla. Si tiene una tabla ORDERS, el siguiente reemplazo para la FROM DUALcláusula funcionaría:

FROM   orders
WHERE  rownum =1

Sustituya cualquier tabla o vista que pueda seleccionar y funcionará. Sustituya una tabla o vista de la que no pueda seleccionar y fallará. DUALes más confiable ya que impide que un DBA lo rompa, todos los usuarios pueden seleccionarlo y obtendrán solo una fila en el conjunto de resultados. (Se rompe ocasionalmente).

No conozco un verbo que cumpla con los estándares para acceder a datos que no están en una tabla sin incluir una referencia de tabla. Dado lo poco que accedo a esos datos, no veo tanta necesidad. Muchos de los casos con los que me encuentro pueden manejarse mejor de diferentes maneras.

BillThor
fuente
2
SELECT CURRENT_TIMESTAMP FROM (VALUES(1)) V(C)Es compatible con el estándar, creo, y no se basa en ninguna tabla en particular.
Martin Smith
@ MartininSmith He actualizado mi respuesta para usar la referencia de tabla. Esto es lo que quise decir y debería haber especificado.
BillThor