Mengapa saya harus memilih dari tabel ganda?

15

Ini berfungsi dalam Sistem Manajemen Database Relasi utama yang paling mungkin muncul di StackOverflow / dba.stackexchange, menjadi SQL Server, MySQL, PostgreSQL dan SQLite (WebSQL) .

select 'abc' abc, 1 def;

Ini tidak berfungsi pada Oracle. Mengapa kita perlu memilih dari DUAL di Oracle? Apakah standar ISO / ANSI untuk SQL memerlukan klausa FROM untuk pernyataan SELECT ?


Edit:

Per Bacon Bitjawaban, tampaknya memang diperlukan oleh standar SQL.

Jadi pada kenyataannya, karena nama DUAL adalah istilah yang keliru, jika saya membuat tabel dan menamakannya ATOM atau ONE, mis create table one (atom int);. select 'abc' abc, 1 def FROM one;- Apakah ada penalti performa dibandingkan dengan SELECT .. FROM DUAL?

孔夫子
sumber
Saya pikir DB2 juga tidak dapat melakukan selecttanpa from. DB2 memiliki tabel boneka serupa yang disebut SYSIBM.SYSDUMMY1 . Anda juga mungkin sudah mengetahui hal ini, tetapi ketika Anda select 'A' from dual, dualtabel tersebut tidak benar-benar diakses , yang menjawab pertanyaan dalam suntingan Anda (yang pantas menjadi pertanyaan baru btw).
Jack bilang coba topanswers.xyz
1
Itu tidak bekerja di "semua" DBMS. Ada beberapa DBMS yang tidak memungkinkan SELECT tanpa FROM. Manual menjawab pertanyaan Anda tentang kinerja: docs.oracle.com/cd/E11882_01/server.112/e26088/…
a_horse_with_no_name
3
@JackDouglas: Anda benar. DB2 memang membutuhkan FROMklausa. Dari atas kepala saya: Informix, Firebird dan Apache Derby juga memerlukannya.
a_horse_with_no_name
1
DB2 memang membutuhkan klausa FROM, tetapi alternatifnya adalah menggunakan pernyataan like values ('abc', 1). Anda tentu saja dapat juga memilih dari pernyataan seperti itu:select abc from ( values ('abc',1) ) as t(abc,def)
Lennart

Jawaban:

30

Sebenarnya, FROMklausa SELECTpernyataan tidak opsional. Sintaks untuk SQL-99 merinci SELECTstatment dasar , dan FROMklausa tidak memiliki tanda kurung siku di sekitarnya. Itu menunjukkan standar menganggapnya non-opsional:

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]

Dalam penggunaan aktual, pemrogram dan DBA sering merasa berguna untuk melakukan hal-hal selain memanipulasi data dalam tabel atau memanipulasi tabel dan struktur data. Jenis hal ini sebagian besar di luar ruang lingkup standar SQL, yang berkaitan dengan fitur data lebih dari mur dan baut implementasi spesifik. Apakah kami ingin menjalankan SELECT getdate()atau SELECT 1atau SELECT DB_NAME()(atau apa pun yang lebih disukai dialek Anda), kami sebenarnya tidak menginginkan data dari sebuah tabel.

Oracle memilih untuk memecahkan perbedaan standar dan implementasi menggunakan tabel dummy dengan definisi efektif berikut:

CREATE TABLE DUAL (
  DUMMY CHAR(1)
  )

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

RDBMSes lainnya pada dasarnya mengasumsikan bahwa tabel dummy digunakan jika tidak FROMditentukan.

The sejarah tabel DUAL adalah di Wikipedia:

Tabel DUAL dibuat oleh Charles Weiss dari perusahaan Oracle untuk menyediakan tabel untuk bergabung dalam pandangan internal:

Saya membuat tabel DUAL sebagai objek yang mendasari dalam Kamus Data Oracle. Itu tidak pernah dimaksudkan untuk dilihat sendiri, tetapi digunakan di dalam tampilan yang diharapkan akan ditanyakan. Idenya adalah bahwa Anda bisa melakukan GABUNG ke tabel DUAL dan membuat dua baris di hasilnya untuk setiap satu baris di tabel Anda. Kemudian, dengan menggunakan GROUP BY, gabungan yang dihasilkan dapat diringkas untuk menunjukkan jumlah penyimpanan untuk tingkat DATA dan untuk tingkat INDEX. Nama itu, DUAL, tampaknya cocok untuk proses menciptakan sepasang baris dari satu.

Tabel DUAL asli memiliki dua baris di dalamnya (maka namanya), tetapi kemudian hanya memiliki satu baris.

Bit Bacon
sumber
3
+1 dan selamat datang di dba.se. Ini adalah jawaban yang sangat baik dengan sedikit sejarah yang menarik - Saya harap Anda dapat didorong untuk tetap tinggal dan berkontribusi lebih banyak :)
Jack mengatakan coba topanswers.xyz
4
Berjam-jam kesenangan tanpa akhir dimiliki oleh saya sekali ketika seorang pengembang memasukkan beberapa baris lagi menjadi dua. Pecah banyak hal :) Butuh beberapa saat untuk melacak pelakunya!
Philᵀᴹ
8

Keuntungannya dualadalah pengoptimal memahami dualadalah satu baris khusus, satu tabel kolom (dengan varchar2tipe data) - saat Anda menggunakannya dalam kueri, ia menggunakan pengetahuan ini saat mengembangkan rencana.

Mengapa kita harus memilih dari dualdalam Oracle?

Anda dapat memilih dari dualatau dari tabel Anda sendiri juga, Anda bisa jika Anda mau.

Bagi saya, saya akan tetap dengan dualkarena saya tahu dualada. Saya tahu ia memiliki setidaknya 1 dan paling banyak 1 baris. Saya tahu pengoptimal tahu semua tentang dualdan melakukan hal yang paling efisien bagi saya. Pengoptimal memahami dualadalah tabel 1 baris ajaib, khusus. Itu berhenti di select *karena ada satu baris di sana. Jadi begitulah cara kerjanya.

DevYudh
sumber
"Aku tahu setidaknya ada 1 dan paling banyak 1 baris." Nah, seorang brengsek (atau orang idiot) dengan hak istimewa DBA dapat memodifikasiDUAL . Hati-hati!
Nick Chammas
nah kalau itu terjadi padamu. cabut semua hak istimewa kecuali untuk BUAT SESI dari Seseorang ini. dan bagaimana jika dual dijatuhkan secara tidak sengaja oleh seseorang?
DevYudh
Anda dapat membuatnya menggunakan penyimpanan create table dual (dummy varchar2 (1)) (initial 1) atau flashback table dual to before drop
DevYudh
Yah, ini merupakan keuntungan dalam menggunakan DUAL dibandingkan dengan memilih ekspresi dari tabel lain yang ada, tetapi itu tidak menjelaskan apa keuntungan memiliki DUAL sebagai alternatif karena tidak harus memiliki FROM, seperti di PostgreSQL atau SQLServer
Danubian Sailor
@Lukasz Lech di Oracle tidak ada SELECT tanpa FROM untuk #MSSQL Serv: Tidak perlu meja ganda dalam SQL Server sama sekali. tetapi jika Anda mentransfer kode Anda dari oracle ke SQL Serv Anda dapat membuat dua menggunakan skrip ini CREATE TABLE DUAL (DUMMY VARCHAR (1)) GO INSERT INTO DUAL (DUMMY) VALUES (DUMMY) VALUES ('X') GO tetapi, saya tidak melihat adanya alasan untuk menggunakan / membuat tabel ganda di sql server. dan juga MSSQL Serv dan PostGRE SQL tidak memerlukan tabel Dummy
DevYudh
1

Dua jawaban lainnya memberikan latar belakang yang baik untuk jawaban saya.

Pada database Oracle, ini tradisional dan dapat diandalkan. Ini akan gagal pada database lain yang tidak memiliki DUALtabel. Anda tidak perlu menggunakannya DUAL, tetapi saya sarankan Anda melakukannya.

Basis data yang memenuhi standar akan membutuhkan FROMklausa yang menentukan setidaknya referensi Tabel. Jika Anda memiliki tabel PESANAN, penggantian FROM DUALklausa berikut akan berfungsi:

FROM   orders
WHERE  rownum =1

Ganti setiap tabel atau tampilan yang dapat Anda pilih dan itu akan berfungsi. Gantikan tabel atau tampilan yang tidak dapat Anda pilih dan itu akan gagal. DUALlebih dapat diandalkan sebagai pembatasan DBA yang melanggarnya, semua pengguna dapat memilih darinya, dan hanya akan mendapatkan satu baris di set hasil. (Kadang-kadang rusak.)

Saya tidak mengetahui kata kerja yang memenuhi standar untuk mengakses data yang tidak ada dalam tabel tanpa menyertakan referensi Tabel. Mengingat betapa sedikitnya saya mengakses data seperti itu, saya tidak melihat kebutuhan seperti itu. Banyak kasus yang saya alami, dapat ditangani dengan cara yang berbeda.

BillThor
sumber
2
SELECT CURRENT_TIMESTAMP FROM (VALUES(1)) V(C)adalah standar yang saya percaya dan tidak bergantung pada tabel tertentu.
Martin Smith
@ MartinSmith Saya telah memperbarui tanggapan saya untuk menggunakan referensi Tabel. Inilah yang saya maksudkan dan seharusnya saya sebutkan.
BillThor