デュアルテーブルから選択する必要があるのはなぜですか?


15

これは、StackOverflow / dba.stackexchange(SQL Server、MySQL、PostgreSQL、SQLite(WebSQL)など)に表示される可能性が高い主要な関係データベース管理システムで機能します

select 'abc' abc, 1 def;

Oracleでは機能しません。OracleのDUALから選択する必要があるのはなぜですか?SQLのISO / ANSI標準では、SELECTステートメントにFROM句が必要ですか?


編集:

Per Bacon Bitの答えによれば、SQL標準では必須のようです。

名前DUALは、このような誤った名称であるので、私は例えば、テーブルを作成し、ATOMまたはONEという名前をしていたのであれば、現実には、create table one (atom int);... select 'abc' abc, 1 def FROM one;-パフォーマンスの低下はに比べてありますかSELECT .. FROM DUAL


私が考える DB2も行うことはできませんselectなしfrom。DB2には、SYSIBM.SYSDUMMY1と呼ばれる同様のダミーテーブルがあります。また、おそらくこれを既に知っているでしょうが、あなたselect 'A' from dualdualテーブルに実際にアクセスしていない場合、編集中の質問に答えます(これは新しい質問に値します)。
ジャックダグラス

1
「すべて」のDBMSでは機能しませ。FROMなしのSELECTを許可しないDBMSがいくつかあります。マニュアルでは、パフォーマンスについてあなたの質問に答える:docs.oracle.com/cd/E11882_01/server.112/e26088/...
a_horse_with_no_name

3
@JackDouglas:あなたは正しいです。DB2にはFROM句が必要です。私の頭上では、Informix、Firebird、Apache Derbyも必要です。
a_horse_with_no_name

1
DB2にはFROM句が必要ですが、代わりにのようなステートメントを使用することもできvalues ('abc', 1)ます。もちろん、このような声明から選択することもできますselect abc from ( values ('abc',1) ) as t(abc,def)
レナート

回答:


30

厳密には、はい、文のFROM句はSELECTオプションではありません。 SQL-99の構文は基本的なSELECTステートメントの詳細を示しており、FROM句には角括弧がありません。これは、標準がオプションではないと見なしていることを示しています。

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]

実際の使用では、プログラマとDBAは、テーブル内のデータを操作したり、テーブルとデータ構造を操作したりする以外のことを行うことが有用であることがよくあります。このタイプのことは、SQL標準の範囲を大きく超えています。SQL標準は、特定の実装の要点以上にデータ機能に関係しています。実行するSELECT getdate()か、SELECT 1またはSELECT DB_NAME()(または方言が好むものでも)、テーブルからのデータは実際には必要ありません。

オラクルは、次の効果的な定義を持つダミー表を使用して、標準と実装の矛盾を解決することを選択します。

CREATE TABLE DUAL (
  DUMMY CHAR(1)
  )

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

他のRDBMSは、基本的に、FROM指定されていない場合はダミーテーブルが使用されると想定します。

DUALテーブル歴史は Wikipediaにあります:

DUALテーブルは、内部ビューに参加するためのテーブルを提供するために、Oracle CorporationのCharles Weissによって作成されました。

Oracle Data Dictionaryの基礎オブジェクトとしてDUALテーブルを作成しました。それ自体が表示されることを意図したものではなく、クエリが実行されると予想されるビュー内で使用されました。アイデアは、DUALテーブルにJOINを実行し、テーブルの1行ごとに結果に2行を作成できるというものでした。次に、GROUP BYを使用して、結果の結合を要約して、DATAエクステントおよびINDEXエクステントのストレージ量を表示できます。DUALという名前は、1つから行のペアを作成するプロセスに適しているように見えました。

元のDUALテーブルには2つの行がありました(そのため、その名前です)が、その後は1行しかありませんでした。


3
+1およびdba.seへようこそ。これは魅力的な歴史を持つ素晴らしい答えです。もっと頑張って、もっと貢献してくださいと励まされることを願っています:
ジャックダグラス

4
開発者がデュアルにさらにいくつかの行を挿入したとき、私はかつて何時間もの無限の楽しみを経験しました。たくさんのものを壊した:)犯人を追跡するためにしばらく時間がかかった!
Philᵀᴹ

8

dualオプティマイザーが理解する利点dualは、特別な1行、1列のテーブル(varchar2データ型付き)です。クエリで使用する場合、プランの開発時にこの知識を使用します。

dualOracle から選択する必要があるのはなぜですか?

dual必要に応じて、独自のテーブルから選択することもできます。

私にとっては、存在するdualことがわかっているので、私は固執しますdual。少なくとも1行、最大1行あることを知っています。オプティマイザーdualは私にとってすべてを知っており、私にとって最も効率的なことをしています。オプティマイザーdualは、魔法の特別な1行のテーブルであることを理解しています。select *そこに1つの行があるため、停止しました。だからそれはちょうどそれが動作する方法です。


「少なくとも1行、最大1行あることを知っています。」まあ、DBA権限DUAL持つジャーク(またはばか)が変更できます。注意してください!
ニックチャマス

それがあなたに起こったら。この誰かからCREATE SESSIONを除くすべての特権を取り消します。そして、誰かが誤ってデュアルを落とした場合はどうなりますか?
DevYudh

create table dual(dummy varchar2(1))storage(initial 1)またはflashback table dual to to drop
DevYudh

まあ、それは他の既存のテーブルから式を選択するのに比べてDUALを使用することの利点ですが、PostgreSQLやSQLServerのようにFROMを必要としない代替としてDUALを使用する利点を説明していません
Danubian Sailor

Oracleの@Lukasz Lechには、#MSSQL ServにFROMなしのSELECTはありません。SQLServerにデュアルテーブルはまったく必要ありません。しかし、OracleからSQL Servにコードを転送した場合、このスクリプトを使用してデュアルを作成できますCREATE TABLE DUAL(DUMMY VARCHAR(1))GO INSERT INTO DUAL(DUMMY)VALUES( 'X')GOしかし、私は何も表示されませんSQLサーバーでデュアルテーブルを使用/作成する理由。また、MSSQL ServとPostGRE SQLはダミーテーブルを必要としない
DevYudh

1

他の2つの答えは、私の答えの良い背景を提供します。

Oracleデータベースでは、従来の信頼性があります。DUALテーブルを持たない他のデータベースでは失敗します。を使用する必要はありませんが、使用するDUALことをお勧めします。

標準に準拠したデータベースには、FROM少なくともテーブル参照を指定する句が必要です。ORDERSテーブルがある場合、次のFROM DUAL句の置換が機能します。

FROM   orders
WHERE  rownum =1

選択可能なテーブルまたはビューを代用すると、機能します。選択できないテーブルまたはビューを代用すると、失敗します。DUALDBAがそれを壊すことを禁止するより信頼性が高く、すべてのユーザーがそれから選択でき、結果セットで1行のみを取得します。(時々壊れます。)

私は、テーブル参照を含まずにテーブルにないデータにアクセスするための標準準拠の動詞を知りません。そのようなデータにアクセスする量がどれほど少ないかを考えると、そのようなニーズはありません。私が遭遇したケースの多くは、さまざまな方法でうまく処理できます。


2
SELECT CURRENT_TIMESTAMP FROM (VALUES(1)) V(C)私は信じている標準に準拠しており、特定のテーブルに依存していません。
マーティンスミス

@MartinSmithテーブル参照を使用するように応答を更新しました。これは私が意図したものであり、指定すべきでした。
BillThor
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.