Bagaimana cara kerja tabel Oracle DUAL?


32
SQL> desc dual
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 DUMMY                                              VARCHAR2(1)

SQL> select 4*5 from dual;

       4*5
----------
        20

SQL>

Saya merasa sangat aneh. Jika tidak ada kolom bernama 4 * 5 dalam dua kali lipat, bagaimana cara kerja pernyataan pilih?

Juga, mengapa saya tidak melihat perilaku yang sama ketika saya membuat tabel ganda sendiri?

SQL> create table dual2(dummy varchar2(1)); 

Table created.

SQL> desc dual2
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 DUMMY                                              VARCHAR2(1)

SQL> select 4*5 from dual2;

no rows selected

SQL> 

Jawaban:


29

Dari Wikipedia :

Tabel DUAL adalah tabel satu-baris khusus yang hadir secara default di semua instalasi basis data Oracle. Sangat cocok untuk digunakan dalam memilih pseudocolumn seperti SYSDATE atau USER. Tabel memiliki kolom VARCHAR2 (1) tunggal yang disebut DUMMY yang memiliki nilai 'X'.

Dengan demikian, tabel ganda adalah cara untuk melakukan operasi terhadap jumlah apa yang menjadi tabel kosong tetapi tidak nol. Ini berguna ketika seseorang tidak peduli tentang tabel, tetapi perlu melakukan operasi melalui pernyataan pilih. Jika tabel memiliki lebih dari satu baris atau kolom, beberapa hasil akan dikembalikan (karena beroperasi pada seluruh rangkaian tupel saat melakukan operasi.)

Seharusnya tidak digunakan dalam produksi, kecuali jika Anda secara khusus perlu menjalankan prosedur tertentu melalui SQL.

4*5adalah operasi matematika, sama seperti 'Foo' string. Jadi, seperti halnya seseorang dapat memilih 4 * 5 dari tabel mana pun, seperti halnya seseorang dapat memilih 'Foo' dari tabel mana pun, DUAL adalah cara untuk memilihnya dari tabel yang dikenal baik yang tidak akan pernah memiliki banyak hasil.

Dari dokumentasi (KONSEP):

DUAL adalah tabel kecil dalam kamus data yang dapat dirujuk oleh Oracle Database dan program yang ditulis pengguna untuk menjamin hasil yang diketahui. Tabel ganda berguna ketika nilai harus dikembalikan hanya sekali, misalnya, tanggal dan waktu saat ini. Semua pengguna basis data memiliki akses ke DUAL.

Tabel DUAL memiliki satu kolom yang disebut DUMMY dan satu baris yang berisi nilai X.

Dan Referensi SQL :

DUAL adalah tabel yang secara otomatis dibuat oleh Oracle Database bersama dengan kamus data. DUAL ada dalam skema SYS pengguna tetapi dapat diakses dengan nama DUAL untuk semua pengguna. Ini memiliki satu kolom, DUMMY, didefinisikan sebagai VARCHAR2 (1), dan berisi satu baris dengan nilai X. Memilih dari tabel DUAL berguna untuk menghitung ekspresi konstan dengan pernyataan SELECT. Karena DUAL hanya memiliki satu baris, konstanta dikembalikan hanya sekali. Sebagai alternatif, Anda dapat memilih konstanta, pseudocolumn, atau ekspresi dari tabel mana pun, tetapi nilainya akan dikembalikan berkali-kali karena ada baris dalam tabel. Lihat "Tentang Fungsi SQL" untuk banyak contoh memilih nilai konstan dari DUAL.

Dimulai dengan Oracle Database 10g Release 1, I / O logis tidak dilakukan pada tabel DUAL saat menghitung ekspresi yang tidak termasuk kolom DUMMY. Optimasi ini terdaftar sebagai DUAL CEPAT dalam rencana eksekusi. Jika Anda MEMILIH kolom DUMMY dari DUAL, maka pengoptimalan ini tidak terjadi dan terjadi I / O yang logis.


5
"Seharusnya tidak digunakan dalam produksi, kecuali jika Anda secara khusus perlu menjalankan prosedur tertentu melalui SQL" Mengapa tidak?
Nick Pierpoint

2
Saya juga tidak setuju bahwa itu tidak boleh digunakan dalam produksi. Itu terdengar seperti meme "potong ujung daging panggang", bagiku.
ErikE

1
Jawaban ini perlu diperbaiki karena tidak setuju dengan dirinya sendiri. Di satu tempat salinan dari dokumen resmi: "Tabel ganda berguna " dan di tempat lain ia merekomendasikan "Itu tidak boleh digunakan dalam produksi, kecuali ..."
ypercubeᵀᴹ

18

DUAL adalah tabel dengan persis satu baris seperti yang ditampilkan pada pernyataan SQL berikut:

SELECT * FROM dual;

dual2Meja Anda tidak memiliki baris. Jika Anda memasukkan satu, Anda akan melihat perilaku yang sama.

4 * 5 adalah ekspresi yang dapat dievaluasi Oracle tanpa benar-benar menggunakan data dari tabel. Ini akan mengevaluasi satu kali untuk setiap baris, sama seperti yang akan dilakukan dengan ekspresi kolom normal. Jadi jika tidak ada baris, tidak ada hasil yang dikembalikan, jika ada dua baris, Anda akan mendapatkan 20 dua kali.


14

The dualtable "bekerja" hampir hanya cara apapun karya meja lain: itu adalah tabel dari mana Anda dapat memilih catatan.

Ini berarti, misalnya, Anda bisa menggambarkan tabel. Di sini, di SQL*Plus:

SQL> set lines 50
SQL> desc dual
Name                    Null?    Typ
----------------------- -------- ----------------
DUMMY                            VARCHAR2(1)

Jadi, tabel tersebut memiliki satu kolom, bernama dummyyang adalah a varchar2(1).

Tabel tersebut memiliki, menurut desain, satu catatan (setidaknya jika tidak ada yang mengotak-atiknya):

SQL> select count(*) from dual;

COUNT(*)
----------
         1

Jadi, untuk mendapatkan perilaku yang sama dengan yang dual2Anda miliki dual, Anda harus memasukkan satu rekaman menjadi dua. Lebih baik lagi, buat dengan create table as select(cta):

SQL> create table dual2 as select * from dual;

Sekarang, permintaan Anda berfungsi:

SQL> select 4*5 from dual2;
       4*5
----------
        20

Sebelumnya, saya mengatakan bahwa dual hampir berfungsi seperti tabel lainnya. Jadi, kapan itu tidak bekerja seperti meja lainnya?

Itu berperilaku berbeda, jika tidak ada nilai dari tabel itu sendiri dipilih. Sekali lagi, dengan pertanyaan Anda, saya biarkan Oracle menjelaskannya ...

SQL> set lines 150
SQL> explain plan for select 4*5 from dual2;

EXPLAIN PLAN ausgef³hrt.

... untuk melihat bagaimana tabel diakses:

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------
Plan hash value: 3445655939

-------------------------------------------------------------------
| Id  | Operation         | Name  | Rows  | Cost (%CPU)| Time     |
-------------------------------------------------------------------
|   0 | SELECT STATEMENT  |       |     1 |     3   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| DUAL2 |     1 |     3   (0)| 00:00:01 |
-------------------------------------------------------------------

Dapat dilihat bahwa pernyataan itu tidak full table accessaktif dual2.

Sekarang, hal yang sama dengan dual:

SQL> explain plan for select 4*5 from dual;

EXPLAIN PLAN ausgef³hrt.

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
-------------------------------------------------------------------
Plan hash value: 1388734953

-----------------------------------------------------------------
| Id  | Operation        | Name | Rows  | Cost (%CPU)| Time     |
-----------------------------------------------------------------
|   0 | SELECT STATEMENT |      |     1 |     2   (0)| 00:00:01 |
|   1 |  FAST DUAL       |      |     1 |     2   (0)| 00:00:01 |
-----------------------------------------------------------------

Di sinilah dualtabel berperilaku berbeda: nilai dummytidak diperlukan, sehingga fast dualoperasi dijalankan, agar instance tidak membaca nilai aktual pada disk.


10

Secara kebetulan, DUAL adalah salah satu dari beberapa 'tabel' yang berfungsi ketika instance telah dimulai tetapi database belum dibuka.

Anda mendapatkan sesuatu seperti

ADDR     INDX   INST_ID D
-------- ------ ------- -
0C0362D4      0       1 X

9

Selain jawaban lain, Oracle tidak begitu pilih-pilih tentang spasi teks SQL (setidaknya di beberapa tempat). Parser SQL juga tokenizes oleh perbedaan kelas karakter dalam beberapa kasus, bukan hanya oleh spasi.

Misalnya, Anda dapat menjalankan pernyataan seperti itu:

SQL> select * from dual;

D
-
X


SQL> select (1) from dual;

       (1)
----------
         1

SQL> select-null from dual;

     -BATAL
----------


SQL> select-1 from dual;

        -1
----------
        -1

SQL> 

Juga dimungkinkan untuk menjalankan SQL tanpa spasi di dalamnya:

SQL> pilih * dari / ** / dual;

D
-
X

Saya punya beberapa contoh lagi di sini:

http://blog.tanelpoder.com/2008/01/14/can-you-write-a-working-sql-statement-without-using-any-whitespace/

Tanel Poder


2
Kemampuan untuk menghilangkan banyak ruang ini tidak unik untuk Oracle. Bekerja sama di SQL Server.
ErikE

8

Operasi ganda cepat menulis ulang kode Anda ke kueri x $ ganda. Karena "tabel" ini adalah struktur data C dalam SGA, Anda dapat menanyakannya dalam mode nomount.


4

Pertanyaannya sudah dijawab. Ini adalah beberapa catatan untuk tujuan tabel ganda. Ganda dapat digunakan untuk mengevaluasi ekspresi dalam klausa pilih. Banyak sistem basis data lainnya tidak memerlukan tabel seperti itu untuk tujuan ini. MS SQL Server, MySql, Posgres dapat mengevaluasi pernyataan berikut

select 3+5 ;

Oracle tidak bisa. Pernyataan pilih Oracle selalu membutuhkan "from" -clause.

Beberapa fungsi tidak dapat digunakan dalam ekspresi pl / sql seperti DUMP .

Begitu

declare
str varchar2(100);
begin
str:=dump('Hallo');
end;
/

akan memunculkan eksepsi tetapi

declare
str varchar2(100);
begin
select dump('Hallo') into str from dual;
end;
/

akan bekerja.

Itu bisa digunakan untuk memperluas set hasil dari suatu query

select user_id,username from user_users
union all
select -1,'NO USER'
from dual
/

yang memberi

| USER_ID |     USERNAME |
|---------|--------------|
|  476267 | USER_4_E8C50 |
|      -1 |      NO USER |

atau menghasilkan data dengan kueri pilihan menggunakan CONNECT BY:

select level as n 
from dual
connect by level <= 5 ;

atau CTE rekursif:

with nlist(n) as (
  select 1 from dual
  union all
  select n+1
  from nlist 
  where n<5    )
select n
from nlist
 ;

yang kembali

| N |
|---|
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |

di sqlfiddle


3

Untuk apa nilainya, ia bekerja dengan cara yang persis sama di MySQL.

mysql> use test;
Database changed

mysql> create table fred(billy int);
Query OK, 0 rows affected (0.79 sec)

mysql> select 4 + 5 from fred;
Empty set (0.00 sec)

mysql> select 4 + 5 as mary from fred;
Empty set (0.00 sec)

mysql> insert into fred values(1);
Query OK, 1 row affected (0.13 sec)

mysql> select 4 + 5 from fred;
+-------+
| 4 + 5 |
+-------+
|     9 |
+-------+
1 row in set (0.00 sec)

mysql> select 4 + 5 as mary from fred;
+------+
| mary |
+------+
|    9 |
+------+
1 row in set (0.00 sec)

mysql> insert into fred values(2);
Query OK, 1 row affected (0.08 sec)

mysql> select 4 + 5 from fred;
+-------+
| 4 + 5 |
+-------+
|     9 |
|     9 |
+-------+
2 rows in set (0.00 sec)

mysql> select 4 + 5 as mary from fred;
+------+
| mary |
+------+
|    9 |
|    9 |
+------+
2 rows in set (0.00 sec)

mysql> explain select 4 + 5 as mary from fred;
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | fred  | ALL  | NULL          | NULL | NULL    | NULL |    2 | NULL  |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)

mysql> 

Dan juga tampak bahwa DUAL adalah semacam struktur memori di MySQL juga. Perhatikan perbedaan dalam dua menjelaskan rencana - "tidak ada tabel yang digunakan" untuk DUAL di MySQL.

Namun yang menarik, saya tidak dapat melakukan DESC pada dual MySQL, yang berbeda dengan Oracle - tetapi diperkenalkan khusus AIUI untuk memungkinkan sintaks Oracle bekerja pada MySQL.

mysql> select 4 + 5 from dual;
+-------+
| 4 + 5 |
+-------+
|     9 |
+-------+
1 row in set (0.00 sec)

mysql> explain select 4 + 5 from dual;
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra          |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
|  1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | No tables used |
+----+-------------+-------+------+---------------+------+---------+------+------+----------------+
1 row in set (0.00 sec)

mysql> desc dual;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'dual' at line 1
mysql> 

2

Dalam database oracle, tabel ganda pada dasarnya digunakan untuk mendapatkan nilai pseudo-kolom. Ini berisi properti berikut:

  1. Dimiliki oleh pengguna sys
  2. Ini tersedia untuk semua pengguna
  3. Ini hanya berisi satu kolom yang namanya dummy dengan datatype Varchar2 (1), kolom ini dapat memiliki lebar maksimum satu karakter.

Jika Anda ingin mendapatkan detail lebih lanjut, periksa di sini

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.