Bảng Oracle DUAL hoạt động như thế nào?


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

SQL> select 4*5 from dual;

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

SQL>

Tôi thấy nó thực sự kỳ lạ. Nếu không có cột có tên 4 * 5 trong kép, thì câu lệnh select hoạt động như thế nào?

Ngoài ra, tại sao tôi không thấy hành vi tương tự khi tôi tạo bảng kép của riêng mình?

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> 

Câu trả lời:


29

Từ Wikipedia :

Bảng DUAL là bảng một hàng đặc biệt được hiển thị theo mặc định trong tất cả các cài đặt cơ sở dữ liệu của Oracle. Nó phù hợp để sử dụng trong việc chọn một bút danh như SYSDATE hoặc USER. Bảng có một cột VARCHAR2 (1) được gọi là DUMMY có giá trị 'X'.

Do đó, bảng kép là một cách để thực hiện các thao tác đối với số tiền là một bảng trống nhưng không rỗng. Điều này hữu ích khi một người không quan tâm đến bảng, nhưng cần thực hiện các thao tác thông qua một câu lệnh chọn. Nếu bảng có nhiều hàng hoặc cột, nhiều kết quả sẽ được trả về (do hoạt động trên toàn bộ bộ dữ liệu khi thực hiện thao tác.)

Nó không nên được sử dụng trong sản xuất, trừ khi bạn đặc biệt cần phải gọi một số thủ tục nhất định thông qua SQL.

4*5là một phép toán, giống như 'Foo' một chuỗi. Do đó, giống như người ta có thể chọn 4 * 5 từ bất kỳ bảng nào, cũng như người ta có thể chọn 'Foo' từ bất kỳ bảng nào, DUAL là cách chọn nó từ một bảng đã biết sẽ không bao giờ có nhiều kết quả.

Từ tài liệu (KHÁI NIỆM):

DUAL là một bảng nhỏ trong từ điển dữ liệu mà Cơ sở dữ liệu Oracle và các chương trình do người dùng viết có thể tham chiếu để đảm bảo kết quả đã biết. Bảng kép hữu ích khi một giá trị phải được trả về một lần, ví dụ, ngày và giờ hiện tại. Tất cả người dùng cơ sở dữ liệu có quyền truy cập vào DUAL.

Bảng DUAL có một cột được gọi là DUMMY và một hàng chứa giá trị X.

tài liệu tham khảo SQL :

DUAL là một bảng được tạo tự động bởi Cơ sở dữ liệu Oracle cùng với từ điển dữ liệu. DUAL nằm trong lược đồ của người dùng SYS nhưng có thể truy cập bằng tên DUAL cho tất cả người dùng. Nó có một cột, DUMMY, được xác định là VARCHAR2 (1) và chứa một hàng có giá trị X. Chọn từ bảng DUAL rất hữu ích để tính biểu thức hằng với câu lệnh SELECT. Vì DUAL chỉ có một hàng, hằng số chỉ được trả về một lần. Ngoài ra, bạn có thể chọn một hằng số, giả hoặc biểu thức từ bất kỳ bảng nào, nhưng giá trị sẽ được trả về nhiều lần khi có các hàng trong bảng. Tham khảo "Giới thiệu về các hàm SQL" để biết nhiều ví dụ về việc chọn giá trị không đổi từ DUAL.

Bắt đầu với Cơ sở dữ liệu Oracle 10g Phiên bản 1, I / O logic không được thực hiện trên bảng DUAL khi tính toán một biểu thức không bao gồm cột DUMMY. Tối ưu hóa này được liệt kê là NHANH DUAL trong kế hoạch thực hiện. Nếu bạn CHỌN cột DUMMY từ DUAL, thì việc tối ưu hóa này không diễn ra và I / O logic xảy ra.


5
"Nó không nên được sử dụng trong sản xuất, trừ khi bạn đặc biệt cần phải gọi một số thủ tục nhất định thông qua SQL" Tại sao không?
Nick Pierpoint

2
Tôi cũng không thể đồng ý rằng nó không nên được sử dụng trong sản xuất. Nghe có vẻ giống như một meme "cắt đầu nướng", đối với tôi.
ErikE

1
Câu trả lời này cần cải thiện vì nó không đồng ý với chính nó. Ở một nơi, nó sao chép từ các tài liệu chính thức: "Bảng kép rất hữu ích " và ở một nơi khác, nó khuyến nghị "Không nên sử dụng nó trong sản xuất, trừ khi ..."
ypercubeᵀᴹ

18

DUAL là một bảng có chính xác một hàng như câu lệnh SQL sau sẽ hiển thị:

SELECT * FROM dual;

dual2Bảng của bạn không có hàng. Nếu bạn chèn một, bạn sẽ thấy hành vi tương tự.

4 * 5 là một biểu thức mà Oracle có thể đánh giá mà không thực sự sử dụng dữ liệu từ bảng. Nó sẽ đánh giá nó một lần cho mỗi hàng, giống như nó sẽ làm với biểu thức cột bình thường. Vì vậy, nếu không có hàng, không có kết quả nào được trả về, nếu có hai hàng, bạn sẽ nhận được 20 lần.


14

Các dualbảng "hoạt động" gần như chỉ là bất kỳ cách nào các công trình bảng khác: nó là một bảng mà từ đó bạn có thể chọn hồ sơ.

Điều này có nghĩa, ví dụ, bạn có thể mô tả bảng. Ở đây, trong SQL*Plus:

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

Vì vậy, bảng có một cột, được đặt tên dummylà a varchar2(1).

Bảng này, theo thiết kế, một bản ghi (ít nhất là nếu không có ai chơi với nó):

SQL> select count(*) from dual;

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

Vì vậy, để có được hành vi tương tự dual2như bạn có dual, bạn phải chèn một bản ghi thành kép. Tốt hơn nữa, tạo nó với một create table as select(ctas):

SQL> create table dual2 as select * from dual;

Bây giờ, truy vấn của bạn hoạt động:

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

Trước đó, tôi đã nói rằng dual gần như hoạt động như bất kỳ bảng nào khác. Vì vậy, khi nó không hoạt động như bất kỳ bảng khác?

Nó hoạt động khác nhau, nếu không có giá trị từ chính bảng được chọn. Một lần nữa, với các truy vấn của bạn, tôi để Oracle giải thích chúng ...

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

EXPLAIN PLAN ausgef³hrt.

... Để xem cách truy cập bảng:

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 |
-------------------------------------------------------------------

Có thể thấy rằng tuyên bố thực hiện một full table accesstrên dual2.

Bây giờ, điều tương tự với 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 |
-----------------------------------------------------------------

Đây là nơi dualbảng hoạt động khác nhau: giá trị của dummykhông cần thiết, do đó, một fast dualthao tác được thực thi, để cá thể không đọc giá trị thực trên đĩa.


10

Ngẫu nhiên, DUAL là một trong số ít các 'bảng' hoạt động khi thể hiện đã được khởi động nhưng cơ sở dữ liệu chưa được mở.

Bạn nhận được một cái gì đó như

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

9

Ngoài các câu trả lời khác, Oracle không quá cầu kỳ về văn bản SQL khoảng trống (ít nhất là ở một số nơi). Trình phân tích cú pháp SQL cũng token hóa bởi sự khác biệt của lớp ký tự trong một số trường hợp, không chỉ bởi khoảng trắng.

Ví dụ: bạn có thể chạy các câu lệnh như vậy:

SQL> chọn * từ kép;

D
-
X


SQL> chọn (1) từ kép;

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

SQL> chọn-null từ kép;

     -VÔ GIÁ TRỊ
----------


SQL> select-1 từ kép;

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

SQL> 

Cũng có thể chạy SQL mà không cần bất kỳ khoảng trắng nào trong đó:

SQL> chọn * từ / ** / dual;

D
-
X

Tôi có một số ví dụ nữa ở đây:

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

Tanel Poder


2
Khả năng bỏ sót nhiều khoảng trống này không phải là duy nhất đối với Oracle. Hoạt động tương tự trong SQL Server.
ErikE

8

Một hoạt động kép nhanh chóng viết lại mã của bạn để truy vấn x $ dual. Vì "bảng" này là cấu trúc dữ liệu C trong SGA, bạn có thể truy vấn nó trong chế độ định danh.


4

Câu hỏi đã được trả lời. Đây là một số lưu ý cho mục đích của bảng kép. Dual có thể được sử dụng để đánh giá biểu thức trong mệnh đề chọn. Nhiều hệ thống cơ sở dữ liệu khác không cần một bảng như vậy cho mục đích này. MS SQL Server, MySql, Posgres có thể đánh giá câu lệnh sau

select 3+5 ;

Oracle không thể. Một câu lệnh chọn của Oracle luôn cần một "từ".

Một số hàm không thể được sử dụng trong biểu thức pl / sql như DUMP .

Vì thế

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

sẽ đưa ra một ngoại lệ nhưng

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

sẽ làm việc.

Nó có thể được sử dụng để mở rộng tập kết quả của một truy vấn

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

mà đã cho

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

hoặc tạo dữ liệu với các truy vấn chọn bằng cách sử dụng CONNECT BY:

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

hoặc CTE đệ quy:

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

trả về

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

trong sqlfiddle


3

Đối với những gì nó có giá trị, nó hoạt động chính xác theo cách tương tự trong 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> 

Và cũng có vẻ như DUAL là một loại cấu trúc bộ nhớ trong MySQL. Lưu ý sự khác biệt trong hai kế hoạch giải thích - "không sử dụng bảng" cho DUAL trong MySQL.

Tuy nhiên, điều thú vị là tôi không thể thực hiện một DESC trên nền tảng kép của MySQL, khác với Oracle - nhưng nó được giới thiệu cụ thể là AIUI để cho phép cú pháp của Oracle hoạt động trên 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

Trong cơ sở dữ liệu oracle, bảng Dual về cơ bản được sử dụng để lấy giá trị của các cột giả. Nó chứa các thuộc tính sau:

  1. Nó thuộc sở hữu của người dùng sys
  2. Nó có sẵn cho tất cả người dùng
  3. Nó chỉ chứa một cột có tên giả với kiểu dữ liệu Varchar2 (1), Cột này có thể có chiều rộng tối đa của một ký tự.

Nếu bạn muốn biết thêm chi tiết, kiểm tra ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.