Tại sao tôi phải chọn từ bảng kép?


15

Điều này hoạt động trong các Hệ thống quản lý cơ sở dữ liệu quan hệ rất có thể xuất hiện trên StackOverflow / dba.stackexchange, là SQL Server, MySQL, PostgreQuery và SQLite (WebQuery) .

select 'abc' abc, 1 def;

Nó không hoạt động trên Oracle. Tại sao chúng ta cần chọn từ DUAL trong Oracle? Tiêu chuẩn ISO / ANSI cho SQL có yêu cầu mệnh đề TỪ cho các câu lệnh CHỌN không?


Biên tập:

Mỗi Bacon Bitcâu trả lời, có vẻ như tiêu chuẩn SQL yêu cầu.

Vì vậy, trong thực tế, vì tên DUAL là một cách gọi sai, nếu tôi tạo một bảng và đặt tên là ATOM hoặc ONE, ví dụ create table one (atom int);.. select 'abc' abc, 1 def FROM one;- Có bị phạt hiệu suất so với SELECT .. FROM DUALkhông?


Tôi nghĩ rằng DB2 cũng không thể làm selectmà không có a from. DB2 có một bảng giả tương tự được gọi là SYSIBM.SYSDUMMY1 . Ngoài ra, bạn có thể đã biết điều này, nhưng khi bạn select 'A' from dual, dualbảng không thực sự được truy cập , câu trả lời cho câu hỏi trong chỉnh sửa của bạn (có công cho một câu hỏi mới btw).
Jack Douglas

1
không hoạt động trong "tất cả" DBMS. Có một số DBMS không cho phép CHỌN mà không có TỪ. Hướng dẫn trả lời câu hỏi của bạn về hiệu suất: docs.oracle.com/cd/E11882_01/server.112/e26088/ mẹo
a_horse_with_no_name

3
@JackDoumund: Bạn nói đúng. DB2 không yêu cầu một FROMmệnh đề. Ngoài đỉnh đầu của tôi: Informix, Firebird và Apache Derby cũng yêu cầu điều đó.
a_horse_with_no_name

1
DB2 yêu cầu một mệnh đề TỪ, nhưng một cách khác là sử dụng một câu lệnh như thế nào values ('abc', 1). Tất nhiên bạn cũng có thể chọn từ tuyên bố như vậy:select abc from ( values ('abc',1) ) as t(abc,def)
Lennart

Câu trả lời:


30

Nghiêm túc, có, FROMmệnh đề của một SELECTtuyên bố không phải là tùy chọn. Cú pháp cho SQL-99 nêu chi tiết về thống kê cơ bản SELECTFROMmệnh đề không có bất kỳ dấu ngoặc vuông nào xung quanh nó. Điều đó cho thấy tiêu chuẩn coi nó là không tùy chọn:

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]

Trong sử dụng thực tế, các lập trình viên và DBA thường thấy hữu ích khi làm những việc khác ngoài thao tác dữ liệu trong bảng hoặc thao tác với bảng và cấu trúc dữ liệu. Loại điều này phần lớn nằm ngoài phạm vi của tiêu chuẩn SQL, liên quan đến các tính năng dữ liệu nhiều hơn các loại hạt và bu lông của việc triển khai cụ thể. Cho dù chúng ta muốn chạy SELECT getdate()hoặc SELECT 1hoặc SELECT DB_NAME()(hoặc bất kỳ phương ngữ của bạn thích), chúng tôi không thực sự muốn dữ liệu từ một bảng.

Oracle chọn giải quyết sự khác biệt về tiêu chuẩn và triển khai bằng cách sử dụng bảng giả với định nghĩa hiệu quả sau:

CREATE TABLE DUAL (
  DUMMY CHAR(1)
  )

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

Các RDBMS khác về cơ bản giả định rằng một bảng giả được sử dụng nếu không FROMđược chỉ định.

Các lịch sử của bảng DUAL là trên Wikipedia:

Bảng DUAL được tạo bởi Charles Weiss của tập đoàn Oracle để cung cấp một bảng để tham gia vào các khung nhìn nội bộ:

Tôi đã tạo bảng DUAL như một đối tượng cơ bản trong Từ điển dữ liệu Oracle. Nó không bao giờ có nghĩa là được nhìn thấy chính nó, mà thay vào đó được sử dụng trong một khung nhìn dự kiến ​​sẽ được truy vấn. Ý tưởng là bạn có thể thực hiện THAM GIA với bảng DUAL và tạo hai hàng trong kết quả cho mỗi một hàng trong bảng của bạn. Sau đó, bằng cách sử dụng GROUP BY, phép nối kết quả có thể được tóm tắt để hiển thị dung lượng lưu trữ cho phạm vi DATA và cho phạm vi INDEX. Tên, DUAL, dường như thích hợp cho quá trình tạo một cặp hàng chỉ từ một.

Bảng DUAL ban đầu có hai hàng trong đó (vì vậy tên của nó), nhưng sau đó nó chỉ có một hàng.


3
+1 và chào mừng bạn đến với dba.se. Đây là một câu trả lời tuyệt vời với một chút lịch sử hấp dẫn. Tôi hy vọng bạn có thể được khuyến khích gắn bó và đóng góp nhiều hơn :)
Jack Douglas

4
Tôi đã có hàng giờ vui vẻ bất tận khi một nhà phát triển chèn thêm một vài hàng vào kép. Đã phá vỡ nhiều thứ :) Mất một lúc để truy tìm thủ phạm!
Phil

8

Ưu điểm duallà trình tối ưu hóa hiểu duallà một hàng đặc biệt, một bảng cột (với varchar2kiểu dữ liệu) - khi bạn sử dụng nó trong các truy vấn, nó sử dụng kiến ​​thức này khi phát triển kế hoạch.

Tại sao chúng ta cần phải chọn từ dualtrong Oracle?

Bạn cũng có thể chọn từ dualhoặc từ các bảng của riêng mình, bạn có thể nếu bạn muốn.

Đối với tôi, tôi sẽ gắn bó dualvì tôi biết dualcó tồn tại. Tôi biết nó có ít nhất 1 và nhiều nhất là 1 hàng. Tôi biết trình tối ưu hóa biết tất cả về dualvà làm điều hiệu quả nhất cho tôi. Trình tối ưu hóa hiểu duallà một bảng 1 hàng kỳ diệu. Nó dừng lại select *vì có một hàng trong đó. Vì vậy, nó chỉ là cách nó hoạt động.


"Tôi biết nó có ít nhất 1 và nhiều nhất là 1 hàng." Chà, một thằng ngốc (hoặc một thằng ngốc) với đặc quyền DBA có thể sửa đổiDUAL . Hãy cẩn thận!
Nick Chammas

tốt nếu điều đó xảy ra với bạn. thu hồi tất cả các đặc quyền ngoại trừ TẠO PHẦN từ người này. và điều gì xảy ra nếu dual bị vô tình đánh rơi bởi ai đó?
DevYudh

bạn có thể tạo nó bằng cách sử dụng lưu trữ tạo bảng kép (dummy varchar2 (1)) (ban đầu 1) hoặc bảng hồi tưởng kép trước khi thả
DevYudh

Chà, đó là một lợi thế khi sử dụng DUAL so với việc chọn biểu thức từ bất kỳ bảng hiện có nào khác, nhưng nó không giải thích lợi thế của việc có DUAL thay thế cho việc không phải có TỪ, như trong PostgreQuery hoặc SQLServer
Danubian Sailor

@Lukasz Lech trong Oracle không có CHỌN mà không TỪ cho #MSSQL Serv: Không cần bảng Dual trong SQL Server. nhưng nếu bạn đã chuyển mã của mình từ oracle sang SQL Serv, bạn có thể tạo mã kép bằng cách sử dụng tập lệnh này TẠO TABLE DUAL (DUMMY VARCHAR (1)) GO INSERT INTO DUAL (DUMMY) VALUES ('X') GO nhưng, tôi không thấy bất kỳ lý do để sử dụng / tạo bảng Dual trong máy chủ sql. và MSSQL Serv và PostGRE SQL không yêu cầu bảng giả
DevYudh

1

Hai câu trả lời khác cung cấp nền tảng tốt cho câu trả lời của tôi.

Trên cơ sở dữ liệu của Oracle, nó là truyền thống và đáng tin cậy. Nó sẽ thất bại trên các cơ sở dữ liệu khác không có DUALbảng. Bạn không cần thiết phải sử dụng DUAL, nhưng tôi khuyên bạn nên làm.

Cơ sở dữ liệu tuân thủ tiêu chuẩn sẽ yêu cầu một FROMđiều khoản chỉ định ít nhất Bảng tham chiếu. Nếu bạn có bảng ORDERS, thay thế sau cho FROM DUALmệnh đề sẽ hoạt động:

FROM   orders
WHERE  rownum =1

Thay thế bất kỳ bảng hoặc chế độ xem bạn có thể chọn và nó sẽ hoạt động. Thay thế một bảng hoặc xem bạn không thể chọn và nó sẽ thất bại. DUALđáng tin cậy hơn khi chặn một DBA phá vỡ nó, tất cả người dùng có thể chọn từ nó và sẽ chỉ nhận được một hàng trong tập kết quả. (Nó thỉnh thoảng bị hỏng.)

Tôi không biết về một động từ tuân thủ tiêu chuẩn để truy cập dữ liệu không có trong bảng mà không bao gồm tham chiếu Bảng. Cho rằng tôi ít truy cập dữ liệu như vậy, tôi không thấy nhu cầu như vậy. Nhiều trường hợp tôi gặp phải, có thể được xử lý tốt hơn theo những cách khác nhau.


2
SELECT CURRENT_TIMESTAMP FROM (VALUES(1)) V(C)Tôi tuân thủ tiêu chuẩn và tôi không dựa vào bất kỳ bảng cụ thể nào.
Martin Smith

@MartinSmith Tôi đã cập nhật phản hồi của mình để sử dụng Bảng tham chiếu. Đây là những gì tôi có nghĩa và nên đã chỉ định.
BillThor
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.