Tóm lược
Không có lý do hợp lý nào không thể thực hiện được, nhưng lợi ích thì nhỏ và có một số cạm bẫy có thể không rõ ràng ngay lập tức.
Kết quả nghiên cứu
Tôi đã làm một số nghiên cứu và tìm thấy một số thông tin tốt. Sau đây là trích dẫn trực tiếp từ một nguồn chính đáng tin cậy (muốn ẩn danh) vào lúc 2012-08-09 17:49 GMT:
Khi SQL lần đầu tiên được phát minh, nó không có bí danh trong mệnh đề SELECT. Đây là một thiếu sót nghiêm trọng đã được sửa chữa khi ngôn ngữ được ANSI chuẩn hóa vào khoảng năm 1986.
Ngôn ngữ được dự định là "phi thủ tục" - nói cách khác, để mô tả dữ liệu bạn muốn mà không chỉ định cách tìm nó. Vì vậy, theo như tôi biết, không có lý do nào khiến việc triển khai SQL không thể phân tích toàn bộ truy vấn trước khi xử lý nó và cho phép các bí danh được xác định ở bất cứ đâu và được sử dụng ở mọi nơi. Ví dụ: tôi không thấy bất kỳ lý do nào khiến truy vấn sau không hợp lệ:
select name, salary + bonus as pay
from employee
where pay > 100000
Mặc dù tôi nghĩ rằng đây là một truy vấn hợp lý, một số hệ thống dựa trên SQL có thể đưa ra các hạn chế trong việc sử dụng bí danh vì một số lý do liên quan đến triển khai. Tôi không ngạc nhiên khi biết rằng SQL Server làm điều này.
Tôi quan tâm đến nghiên cứu sâu hơn về tiêu chuẩn SQL-86 và tại sao các DBMS hiện đại không hỗ trợ tái sử dụng bí danh, nhưng vẫn chưa có thời gian để đi xa với nó. Để bắt đầu, tôi không biết lấy tài liệu ở đâu hoặc làm thế nào để tìm ra chính xác ai là người tạo nên ủy ban. Bất cứ ai có thể giúp đỡ? Tôi cũng muốn biết thêm về sản phẩm Sybase gốc mà SQL Server đến từ.
Từ nghiên cứu này và một số suy nghĩ xa hơn, tôi đã nghi ngờ rằng việc sử dụng bí danh trong các mệnh đề khác, trong khi hoàn toàn có thể, đơn giản chưa bao giờ là ưu tiên cao đối với các nhà sản xuất DBMS so với các tính năng ngôn ngữ khác. Vì nó không phải là một trở ngại quá lớn, nên người viết truy vấn dễ dàng làm việc xung quanh, nên nỗ lực vượt qua các tiến bộ khác là không tối ưu. Ngoài ra, nó sẽ là độc quyền vì rõ ràng nó không phải là một phần của tiêu chuẩn SQL (mặc dù tôi đang chờ đợi để tìm hiểu thêm về điều đó) và do đó sẽ là một cải tiến nhỏ, phá vỡ khả năng tương thích SQL giữa các DBMS. Nếu so sánh, CROSS APPLY
(thực sự không có gì khác hơn một bảng dẫn xuất cho phép các tham chiếu bên ngoài) là một thay đổi lớn, trong khi độc quyền cung cấp sức mạnh biểu cảm đáng kinh ngạc không dễ dàng thực hiện theo những cách khác.
Vấn đề với việc sử dụng bí danh ở mọi nơi
Nếu bạn cho phép các mục CHỌN được đặt trong mệnh đề WHERE, bạn không chỉ có thể làm nổ tung sự phức tạp của truy vấn (và do đó sự phức tạp của việc tìm kiếm một kế hoạch thực hiện tốt) có thể đưa ra những thứ hoàn toàn phi logic. Thử:
SELECT X + 5 Y FROM MyTable WHERE Y = X
Điều gì xảy ra nếu MyTable đã có cột Y, mệnh đề WHERE đề cập đến điều gì? Giải pháp là sử dụng CTE hoặc bảng dẫn xuất, trong hầu hết các trường hợp sẽ không tốn thêm chi phí nào nhưng đạt được kết quả cuối cùng tương tự. CTE và các bảng dẫn xuất ít nhất thực thi việc giải quyết sự mơ hồ bằng cách cho phép một bí danh chỉ được sử dụng một lần.
Ngoài ra, không sử dụng bí danh trong mệnh đề TỪ có ý nghĩa nổi bật. Bạn không thể làm điều này:
SELECT
T3.ID + (SELECT Min(Interval) FROM Intervals WHERE IntName = 'T') CalcID
FROM
Table1 T
INNER JOIN Table2 T2
ON T2.ID = CalcID
INNER JOIN Table3 T3
ON T2.ID = T3.ID
Đó là một tham chiếu vòng tròn (theo nghĩa là T2 đang bí mật đề cập đến một giá trị từ T3, trước khi bảng đó được trình bày trong danh sách THAM GIA), và rất khó nhìn thấy. Làm thế nào về điều này:
INSERT dbo.FinalTransaction
SELECT
newid() FinalTransactionGUID,
'GUID is: ' + Convert(varchar(50), FinalTransactionGUID) TextGUID,
T.*
FROM
dbo.MyTable T
Bạn muốn đặt cược bao nhiêu rằng hàm newid () sẽ được đưa vào kế hoạch thực hiện hai lần, hoàn toàn bất ngờ làm cho hai cột hiển thị các giá trị khác nhau? Điều gì về khi truy vấn trên được sử dụng mức N sâu trong CTE hoặc bảng dẫn xuất. Tôi đảm bảo rằng vấn đề tồi tệ hơn bạn có thể tưởng tượng. Có đã vấn đề mâu thuẫn nghiêm túc về việc khi mọi thứ được đánh giá chỉ một lần hoặc ít điểm nào trong một kế hoạch truy vấn, và Microsoft cho biết họ sẽ không sửa chữamột số trong số chúng vì chúng thể hiện đại số truy vấn đúng cách - nếu một kết quả không mong muốn, hãy chia truy vấn thành nhiều phần. Cho phép các tham chiếu được xâu chuỗi, phát hiện các tham chiếu vòng tròn thông qua các chuỗi có khả năng rất dài như vậy, đây là những vấn đề khá khó khăn. Giới thiệu song song và bạn đã có một cơn ác mộng trong quá trình thực hiện.
Lưu ý: Sử dụng bí danh trong WHERE hoặc GROUP BY sẽ không tạo ra sự khác biệt cho các vấn đề với các hàm như newid () hoặc rand ().
Một cách SQL Server để tạo các biểu thức có thể sử dụng lại
CROSS ỨNG DỤNG / OUTER ỨNG DỤNG là một cách trong SQL Server để tạo các biểu thức có thể được sử dụng ở bất kỳ nơi nào khác trong truy vấn (không sớm hơn trong mệnh đề TỪ):
SELECT
X.CalcID
FROM
Table1 T
INNER JOIN Table3 T3
ON T.ID = T3.ID
CROSS APPLY (
SELECT
T3.ID + (SELECT Min(Interval) FROM Intervals WHERE IntName = 'T') CalcID
) X
INNER JOIN Table2 T2
ON T2.ID = X.CalcID
Điều này có hai điều:
- Làm cho tất cả các biểu thức trong CROSS ỨNG DỤNG có được một "không gian tên" (bí danh bảng, ở đây, X) và là duy nhất trong không gian tên đó.
- Làm cho nó rõ ràng ở khắp mọi nơi không chỉ là CalcID đến từ X, mà còn làm rõ lý do tại sao bạn không thể sử dụng bất cứ thứ gì từ X khi tham gia bảng T1 và T3, vì X chưa được giới thiệu.
Tôi thực sự khá thích CROSS ỨNG DỤNG. Nó đã trở thành người bạn trung thành của tôi và tôi sử dụng nó mọi lúc. Cần một UNPIVOT một phần (sẽ yêu cầu PIVOT / UNPIVOT hoặc UNPIVOT / PIVOT bằng cú pháp riêng)? Thực hiện với CROSS ỨNG DỤNG. Cần một giá trị tính toán sẽ được sử dụng lại nhiều lần? Làm xong. Cần cứng nhắc thực thi lệnh thực thi cho các cuộc gọi qua máy chủ được liên kết? Xong - với một sự cải thiện đáng sợ về tốc độ. Chỉ cần một loại hàng tách thành 2 hàng hoặc có thêm điều kiện? Làm xong.
Vì vậy, ít nhất, trong DBMS SQL Server 2005 trở lên, bạn không còn lý do nào để khiếu nại: CROSS ỨNG DỤNG là cách bạn DRY theo cách bạn muốn.