Perché devo selezionare dalla doppia tabella?


15

Funziona con i principali sistemi di gestione dei database di relazione che molto probabilmente compaiono su StackOverflow / dba.stackexchange, essendo SQL Server, MySQL, PostgreSQL e SQLite (WebSQL) .

select 'abc' abc, 1 def;

Non funziona su Oracle. Perché è necessario selezionare DUAL in Oracle? Lo standard ISO / ANSI per SQL richiede una clausola FROM per le istruzioni SELECT ?


Modificare:

Per Bacon Bitla risposta, sembra richiesto dallo standard SQL.

Quindi, in realtà, poiché il nome DUAL è un termine improprio, se dovessi creare una tabella e denominarla ATOM o ONE, ad es create table one (atom int);. select 'abc' abc, 1 def FROM one;- C'è una penalità di prestazione rispetto a SELECT .. FROM DUAL?


Penso che anche DB2 non possa fare a selectsenza a from. DB2 ha una tabella fittizia simile chiamata SYSIBM.SYSDUMMY1 . Probabilmente lo saprai già, ma quando non si accede realmenteselect 'A' from dual alla dualtabella , che risponde alla domanda nella modifica (che meritava una nuova domanda tra l'altro).
Jack dice di provare topanswers.xyz il

1
Esso non funziona in "tutti" i DBMS. Esistono diversi DBMS che non consentono un SELECT senza un FROM. Il manuale risponde alla tua domanda sulle prestazioni: docs.oracle.com/cd/E11882_01/server.112/e26088/…
a_horse_with_no_name

3
@JackDouglas: hai ragione. DB2 richiede una FROMclausola. In cima alla mia testa: Informix, Firebird e Apache Derby lo richiedono anche.
a_horse_with_no_name

1
DB2 richiede una clausola FROM, ma un'alternativa è utilizzare un'istruzione like values ('abc', 1). Ovviamente puoi anche scegliere da tale affermazione:select abc from ( values ('abc',1) ) as t(abc,def)
Lennart,

Risposte:


30

In senso stretto, sì, la FROMclausola di SELECTun'istruzione non è facoltativa. La sintassi per SQL-99 descrive in dettaglio lo SELECTstatment di base e la FROMclausola non ha parentesi quadre attorno. Ciò indica che lo standard lo considera non opzionale:

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]

Nell'uso effettivo, i programmatori e i DBA trovano spesso utile fare cose diverse dalla manipolazione dei dati nelle tabelle o dalle tabelle e dalle strutture dei dati. Questo tipo di cose va ampiamente al di là dell'ambito dello standard SQL, che si occupa delle caratteristiche dei dati più che degli elementi di base di implementazioni specifiche. Sia che vogliamo eseguire SELECT getdate()o SELECT 1o SELECT DB_NAME()(o qualunque cosa il tuo dialetto preferisca), in realtà non vogliamo dati da una tabella.

Oracle sceglie di risolvere la discrepanza standard e di implementazione utilizzando una tabella fittizia con la seguente definizione efficace:

CREATE TABLE DUAL (
  DUMMY CHAR(1)
  )

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

Altri RDBMS presuppongono essenzialmente che venga utilizzata una tabella fittizia se non FROMviene specificato alcun valore .

Il storia della tabella DUAL è su Wikipedia:

La tabella DUAL è stata creata da Charles Weiss della Oracle Corporation per fornire una tabella per l'unione nelle viste interne:

Ho creato la tabella DUAL come oggetto sottostante in Oracle Data Dictionary. Non è mai stato pensato per essere visto da solo, ma invece è stato usato all'interno di una vista che avrebbe dovuto essere interrogata. L'idea era che si potesse fare un JOIN alla tabella DUAL e creare due righe nel risultato per ogni riga della tabella. Quindi, utilizzando GROUP BY, il join risultante potrebbe essere riassunto per mostrare la quantità di memoria per l'estensione DATA e per l'estensione (i) INDICE. Il nome, DUAL, sembrava adatto al processo di creazione di una coppia di righe da una sola.

La tabella DUAL originale aveva due righe (da cui il suo nome), ma successivamente aveva solo una riga.


3
+1 e benvenuto su dba.se. Questa è una risposta eccellente con un po 'di storia affascinante — spero che tu possa essere incoraggiato a restare e contribuire di più :)
Jack dice che prova topanswers.xyz il

4
Ore di divertimento senza fine sono state godute da me una volta quando uno sviluppatore ha inserito alcune altre righe nel doppio. Ha rotto un sacco di cose :) Ci è voluto un po 'per rintracciare il colpevole!
Phil,

8

Il vantaggio dualè che l'ottimizzatore comprendedual è una tabella speciale di una riga, una colonna (con varchar2tipo di dati): quando lo si utilizza nelle query, utilizza questa conoscenza durante lo sviluppo del piano.

Perché dobbiamo selezionare da dual in Oracle?

Puoi selezionare da dual o dai tuoi tavoli, se lo desideri.

Per quanto mi riguarda, resterò fedele dualperché so che dualesiste. So che ha almeno 1 e al massimo 1 riga. So che l'ottimizzatore sa tutto duale fa la cosa più efficiente per me. L'ottimizzatore comprende che dualè una tabella magica, speciale a 1 riga. Si è fermato sul select *perché ci deve essere una riga lì dentro. Quindi funziona così.


"So che ha almeno 1 e al massimo 1 riga." Bene, un coglione (o un idiota) con privilegi DBA può modificareDUAL . Stai attento!
Nick Chammas,

bene se ti succede. revoca tutti i privilegi tranne CREATE SESSION da questa persona Qualcuno. e se il dual fosse lasciato cadere accidentalmente da qualcuno?
DevYudh,

puoi crearlo usando crea tabella dual (dummy varchar2 (1)) storage (iniziale 1) o tabella di flashback doppia rispetto a prima della caduta
DevYudh,

Bene, è un vantaggio nell'uso di DUAL rispetto alla selezione dell'espressione da qualsiasi altra tabella esistente, ma non spiega quale sia il vantaggio di avere DUAL come alternativa per non avere DA, come in PostgreSQL o SQLServer
Danubian Sailor

@Lukasz Lech in Oracle non esiste SELECT senza FROM per #MSSQL Serv: non è necessario utilizzare la doppia tabella in SQL Server. ma se hai trasferito il tuo codice da Oracle a SQL Serv puoi crearne due usando questo script CREATE TABLE DUAL (DUMMY VARCHAR (1)) GO INSERT INTO DUAL (DUMMY) VALUES ('X') GO ma non vedo alcun motivo per utilizzare / creare una tabella doppia nel server sql. e anche MSSQL Serv e PostGRE SQL non richiedono tabella fittizia
DevYudh,

1

Le altre due risposte forniscono un buon background per la mia risposta.

Sui database Oracle, è tradizionale e affidabile. Fallirà su altri database che non hanno una DUALtabella. Non è necessario che tu usi DUAL, ma ti consiglio di farlo.

I database conformi agli standard richiederanno una FROMclausola che specifica almeno il riferimento alla tabella. Se si dispone di una tabella ORDINI, la seguente sostituzione per la FROM DUALclausola funzionerebbe:

FROM   orders
WHERE  rownum =1

Sostituisci qualsiasi tabella o vista che puoi selezionare e funzionerà. Sostituisci una tabella o una vista che non puoi selezionare e fallirà. DUALè più affidabile se si impedisce a un DBA di romperlo, tutti gli utenti possono selezionarlo e otterrà solo una riga nel set di risultati. (Si rompe di tanto in tanto.)

Non sono a conoscenza di un verbo conforme agli standard per l'accesso ai dati che non si trova in una tabella senza includere un riferimento alla tabella. Dato quanto poco accedo a tali dati, non vedo una tale necessità. Molti dei casi in cui mi imbatto, possono essere gestiti meglio in diversi modi.


2
SELECT CURRENT_TIMESTAMP FROM (VALUES(1)) V(C)è conforme allo standard credo e non si basa su alcuna tabella particolare.
Martin Smith,

@MartinSmith Ho aggiornato la mia risposta per utilizzare la tabella di riferimento. Questo è ciò che intendevo e avrei dovuto specificare.
BillThor,
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.