Warum muss ich aus der Doppeltabelle auswählen?

15

Dies funktioniert in den wichtigsten Relation Database Management-Systemen, die am wahrscheinlichsten in StackOverflow / dba.stackexchange vorkommen: SQL Server, MySQL, PostgreSQL und SQLite (WebSQL) .

select 'abc' abc, 1 def;

Unter Oracle funktioniert es nicht. Warum müssen wir in Oracle aus DUAL auswählen? Erfordert der ISO / ANSI-Standard für SQL eine FROM-Klausel für SELECT- Anweisungen?


Bearbeiten:

Per Bacon Bit's Antwort scheint es durch den SQL-Standard erforderlich zu sein.

Also in Wirklichkeit, weil der Name DUAL so eine Fehlbezeichnung ist, wenn ich eine Tabelle erstellen und sie ATOM oder ONE nennen würde, zB create table one (atom int);. select 'abc' abc, 1 def FROM one;- Gibt es eine Leistungsminderung im Vergleich zu SELECT .. FROM DUAL?

孔夫子
quelle
Ich denke, DB2 kann auch selectohne a nicht auskommen from. DB2 verfügt über eine ähnliche Dummy-Tabelle mit dem Namen SYSIBM.SYSDUMMY1 . Das wissen Sie wahrscheinlich auch schon, aber wenn Sie auf select 'A' from dualdie dualTabelle nicht wirklich zugreifen, wird die Frage in Ihrer Bearbeitung beantwortet (die übrigens eine neue Frage verdient hat).
Jack Douglas
1
Es funktioniert nicht in "allen" DBMS. Es gibt mehrere DBMS, die kein SELECT ohne FROM zulassen. Das Handbuch beantwortet Ihre Frage zur Leistung: docs.oracle.com/cd/E11882_01/server.112/e26088/…
a_horse_with_no_name 12.11.12
3
@ JackDouglas: Sie sind richtig. DB2 erfordert eine FROMKlausel. Aus dem Häuschen: Informix, Firebird und Apache Derby benötigen es auch.
a_horse_with_no_name
1
Für DB2 ist eine FROM-Klausel erforderlich, alternativ kann jedoch eine Anweisung wie die folgende verwendet werden values ('abc', 1). Sie können natürlich auch aus solchen Aussagen auswählen:select abc from ( values ('abc',1) ) as t(abc,def)
Lennart

Antworten:

30

Genau genommen ist die FROMKlausel einer SELECTAussage nicht optional. Die Syntax für SQL-99 beschreibt die grundlegenden SELECTAnweisungen, und die FROMKlausel enthält keine eckigen Klammern. Dies zeigt an, dass der Standard dies als nicht optional ansieht:

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]

In der Praxis ist es für Programmierer und Datenbankadministratoren häufig nützlich, andere Aktionen als die Bearbeitung von Daten in Tabellen oder die Bearbeitung von Tabellen und Datenstrukturen durchzuführen. Diese Art von Dingen geht weit über den Geltungsbereich des SQL-Standards hinaus, der sich mehr mit den Datenmerkmalen befasst als mit den Schrauben und Muttern bestimmter Implementierungen. Egal, ob wir ausführen möchten SELECT getdate()oder SELECT 1oder SELECT DB_NAME()(oder was auch immer Ihr Dialekt bevorzugt), wir möchten eigentlich keine Daten aus einer Tabelle.

Oracle entscheidet sich dafür, die Standard- und Implementierungsdiskrepanz mithilfe einer Dummy-Tabelle mit der folgenden effektiven Definition zu beheben:

CREATE TABLE DUAL (
  DUMMY CHAR(1)
  )

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

Andere RDBMS setzen im Wesentlichen voraus, dass eine Dummy-Tabelle verwendet wird, wenn no FROMangegeben ist.

Die Geschichte der DUAL-Tabelle ist auf Wikipedia:

Die DUAL-Tabelle wurde von Charles Weiss vom Oracle-Konzern erstellt, um eine Tabelle für das Zusammenführen interner Ansichten bereitzustellen:

Ich habe die DUAL-Tabelle als zugrunde liegendes Objekt im Oracle Data Dictionary erstellt. Es sollte nie selbst gesehen werden, sondern in einer Ansicht verwendet werden, die abgefragt werden sollte. Die Idee war, dass Sie einen JOIN für die DUAL-Tabelle ausführen und im Ergebnis für jede Zeile in Ihrer Tabelle zwei Zeilen erstellen können. Mithilfe von GROUP BY kann der resultierende Join dann zusammengefasst werden, um die Speichermenge für den DATA-Bereich und den INDEX-Bereich (die INDEX-Bereiche) anzuzeigen. Der Name DUAL schien dafür geeignet zu sein, aus nur einer Zeile ein Zeilenpaar zu erstellen.

Die ursprüngliche DUAL-Tabelle enthielt zwei Zeilen (daher der Name), später jedoch nur eine Zeile.

Speckwürfel
quelle
3
+1 und willkommen bei dba.se. Dies ist eine ausgezeichnete Antwort mit einem faszinierenden Stück Geschichte - ich hoffe, Sie können dazu ermutigt werden, hier zu bleiben und mehr beizutragen :)
Jack Douglas
4
Ich hatte einmal Stunden endlosen Spaßes, als ein Entwickler ein paar Zeilen mehr in dual einfügte. Viele Dinge kaputt gemacht :) Es hat eine Weile gedauert, den Täter aufzuspüren!
Philᵀᴹ
8

Der dualOptimierer hat den Vorteil, dass er dualeine spezielle Tabelle mit einer Zeile und einer Spalte (mit varchar2Datentyp) versteht. Wenn Sie sie in Abfragen verwenden, wird dieses Wissen bei der Entwicklung des Plans verwendet.

Warum müssen wir dualin Oracle eine Auswahl treffen?

Sie können auch aus dualoder aus Ihren eigenen Tabellen auswählen , wenn Sie möchten.

Für mich bleibe dualich dabei, weil ich weiß, dass es dualexistiert. Ich weiß, dass es mindestens 1 und höchstens 1 Zeile hat. Ich weiß, dass der Optimierer alles weiß dualund das effizienteste für mich tut. Der Optimierer versteht dualeine magische, spezielle 1-zeilige Tabelle. Es hörte auf, select *weil es dort eine Reihe geben soll. So funktioniert es einfach.

DevYudh
quelle
"Ich weiß, dass es mindestens 1 und höchstens 1 Zeile hat." Nun, ein Idiot (oder ein Idiot) mit DBA-Berechtigungen kann sich ändernDUAL . Achtung!
Nick Chammas
na wenn dir das passiert alle Privilegien außer CREATE SESSION von dieser Person entziehen. und was ist, wenn Dual versehentlich von jemandem fallen gelassen wurde?
DevYudh
Sie können es mit Create Table Dual (Dummy Varchar2 (1)) -Speicher (Initial 1) oder Flashback Table Dual vor Drop
erstellen
Nun, es ist ein Vorteil bei der Verwendung von DUAL im Vergleich zur Auswahl des Ausdrucks aus einer anderen vorhandenen Tabelle, aber es erklärt nicht, was der Vorteil von DUAL als Alternative ist, wenn kein FROM erforderlich ist, wie in PostgreSQL oder SQLServer
Danubian Sailor
@Lukasz Lech In Oracle gibt es kein SELECT ohne FROM für #MSSQL Serv: In SQL Server wird überhaupt keine Dual-Tabelle benötigt. Aber wenn Sie Ihren Code von Oracle nach SQL Server übertragen haben, können Sie mit diesem Skript Dual erstellen Grund für die Verwendung / Erstellung von Dual-Tabelle in SQL Server. und auch MSSQL Serv und PostGRE SQL benötigen keine Dummy-Tabelle
DevYudh
1

Die beiden anderen Antworten liefern einen guten Hintergrund für meine Antwort.

In Oracle-Datenbanken ist dies traditionell und zuverlässig. Bei anderen Datenbanken, die keine DUALTabelle haben, schlägt dies fehl . Es ist nicht notwendig, dass Sie verwenden DUAL, aber ich würde Ihnen empfehlen, dies zu tun.

Für standardkonforme Datenbanken ist eine FROMKlausel erforderlich , in der mindestens ein Tabellenverweis angegeben ist. Wenn Sie eine ORDERS-Tabelle haben, funktioniert der folgende Ersatz für die FROM DUALKlausel:

FROM   orders
WHERE  rownum =1

Ersetzen Sie jede Tabelle oder Ansicht, aus der Sie auswählen können, und es wird funktionieren. Ersetzen Sie eine Tabelle oder Ansicht, aus der Sie nicht auswählen können, und dies schlägt fehl. DUALDies ist zuverlässiger, da ein Datenbankadministrator es nicht unterbrechen kann. Alle Benutzer können daraus auswählen und erhalten nur eine Zeile in der Ergebnismenge. (Es wird gelegentlich kaputt.)

Mir ist kein standardkonformes Verb für den Zugriff auf Daten bekannt, die sich nicht in einer Tabelle befinden, ohne einen Tabellenverweis anzugeben. Angesichts dessen, wie wenig ich auf solche Daten zugreife, sehe ich keinen solchen Bedarf. Viele der Fälle, auf die ich stoße, können auf unterschiedliche Weise besser behandelt werden.

BillThor
quelle
2
SELECT CURRENT_TIMESTAMP FROM (VALUES(1)) V(C)ist standardkonform, glaube ich, und verlässt sich nicht auf eine bestimmte Tabelle.
Martin Smith
@MartinSmith Ich habe meine Antwort aktualisiert, um die Tabellenreferenz zu verwenden. Dies ist, was ich meinte und hätte angeben sollen.
BillThor