Đây là một vấn đề mà tôi đã dành hàng giờ để nghiên cứu trong quá khứ. Đối với tôi, dường như đây là điều cần được giải quyết bằng các giải pháp RDBMS hiện đại nhưng tôi chưa tìm thấy bất cứ điều gì thực sự giải quyết những gì tôi thấy là một nhu cầu cực kỳ phổ biến trong bất kỳ ứng dụng Web hoặc Windows nào có hỗ trợ cơ sở dữ liệu.
Tôi nói về sắp xếp năng động. Trong thế giới tưởng tượng của tôi, nó sẽ đơn giản như một thứ gì đó như:
ORDER BY @sortCol1, @sortCol2
Đây là ví dụ điển hình được đưa ra bởi các nhà phát triển SQL và Thủ tục lưu trữ mới trên tất cả các diễn đàn trên Internet. "Tại sao điều này là không thể?" họ hỏi. Lúc nào cũng vậy, cuối cùng ai đó cũng đến để giảng cho họ về bản chất tổng hợp của các thủ tục được lưu trữ, về các kế hoạch thực hiện nói chung và tất cả các lý do khác tại sao không thể đưa tham số trực tiếp vào một ORDER BY
mệnh đề.
Tôi biết những gì một số bạn đã nghĩ: "Hãy để khách hàng thực hiện việc sắp xếp." Đương nhiên, điều này giảm tải công việc từ cơ sở dữ liệu của bạn. Tuy nhiên, trong trường hợp của chúng tôi, các máy chủ cơ sở dữ liệu của chúng tôi thậm chí không làm mất 99% thời gian và chúng thậm chí còn không có đa lõi hoặc bất kỳ cải tiến nào khác đối với kiến trúc hệ thống xảy ra cứ sau 6 tháng. Vì lý do này thôi, việc cơ sở dữ liệu của chúng tôi xử lý việc sắp xếp sẽ không thành vấn đề. Ngoài ra, cơ sở dữ liệu rấtgiỏi phân loại. Họ được tối ưu hóa cho nó và đã có nhiều năm để làm cho đúng, ngôn ngữ để thực hiện nó rất linh hoạt, trực quan và đơn giản và trên hết là bất kỳ nhà văn SQL mới bắt đầu nào cũng biết cách làm và thậm chí quan trọng hơn là họ biết cách chỉnh sửa nó, thực hiện thay đổi, bảo trì, v.v. Khi cơ sở dữ liệu của bạn không bị đánh thuế và bạn chỉ muốn đơn giản hóa (và rút ngắn!) thời gian phát triển này có vẻ như là một lựa chọn rõ ràng.
Sau đó là vấn đề web. Tôi đã chơi với JavaScript để sắp xếp các bảng HTML phía máy khách, nhưng chắc chắn chúng không đủ linh hoạt cho nhu cầu của tôi và, một lần nữa, vì cơ sở dữ liệu của tôi không bị đánh thuế quá mức và có thể thực hiện sắp xếp thực sự dễ dàng, tôi có một thời gian khó khăn để chứng minh thời gian cần thiết để viết lại hoặc cuộn trình sắp xếp JavaScript của riêng tôi. Điều tương tự thường xảy ra đối với việc sắp xếp phía máy chủ, mặc dù nó có lẽ đã được ưa thích hơn JavaScript. Tôi không phải là người đặc biệt thích phần trên của DataSets, vì vậy hãy kiện tôi.
Nhưng điều này mang lại điểm không thể - hay nói đúng hơn là không dễ dàng. Tôi đã thực hiện, với các hệ thống trước đó, một cách cực kỳ hack để có được sự sắp xếp động. Nó không đẹp, cũng không trực quan, đơn giản hoặc linh hoạt và một người viết SQL mới bắt đầu sẽ bị mất trong vài giây. Điều này có vẻ không phải là một "giải pháp" mà là một "sự phức tạp".
Các ví dụ sau đây không có nghĩa là để lộ bất kỳ loại thực tiễn tốt nhất hoặc phong cách mã hóa tốt hay bất cứ điều gì, cũng không phải là biểu hiện cho khả năng của tôi với tư cách là một lập trình viên T-SQL. Họ là những gì họ là và tôi hoàn toàn thừa nhận họ là khó hiểu, hình thức xấu, và chỉ đơn giản là hack.
Chúng tôi chuyển một giá trị số nguyên làm tham số cho một thủ tục được lưu trữ (hãy gọi tham số chỉ là "sắp xếp") và từ đó chúng tôi xác định một loạt các biến khác. Ví dụ: giả sử sắp xếp là 1 (hoặc mặc định):
DECLARE @sortCol1 AS varchar(20)
DECLARE @sortCol2 AS varchar(20)
DECLARE @dir1 AS varchar(20)
DECLARE @dir2 AS varchar(20)
DECLARE @col1 AS varchar(20)
DECLARE @col2 AS varchar(20)
SET @col1 = 'storagedatetime';
SET @col2 = 'vehicleid';
IF @sort = 1 -- Default sort.
BEGIN
SET @sortCol1 = @col1;
SET @dir1 = 'asc';
SET @sortCol2 = @col2;
SET @dir2 = 'asc';
END
ELSE IF @sort = 2 -- Reversed order default sort.
BEGIN
SET @sortCol1 = @col1;
SET @dir1 = 'desc';
SET @sortCol2 = @col2;
SET @dir2 = 'desc';
END
Bạn có thể thấy nếu tôi khai báo thêm các biến @colX để xác định các cột khác, tôi thực sự có thể sáng tạo với các cột để sắp xếp dựa trên giá trị của "sort" ... để sử dụng nó, nó thường trông giống như sau mệnh đề cực kỳ lộn xộn:
ORDER BY
CASE @dir1
WHEN 'desc' THEN
CASE @sortCol1
WHEN @col1 THEN [storagedatetime]
WHEN @col2 THEN [vehicleid]
END
END DESC,
CASE @dir1
WHEN 'asc' THEN
CASE @sortCol1
WHEN @col1 THEN [storagedatetime]
WHEN @col2 THEN [vehicleid]
END
END,
CASE @dir2
WHEN 'desc' THEN
CASE @sortCol2
WHEN @col1 THEN [storagedatetime]
WHEN @col2 THEN [vehicleid]
END
END DESC,
CASE @dir2
WHEN 'asc' THEN
CASE @sortCol2
WHEN @col1 THEN [storagedatetime]
WHEN @col2 THEN [vehicleid]
END
END
Rõ ràng đây là một ví dụ rất bị tước bỏ. Các công cụ thực sự, vì chúng ta thường có bốn hoặc năm cột để hỗ trợ sắp xếp, mỗi cột có thể là thứ cấp hoặc thậm chí là cột thứ ba để sắp xếp thêm vào đó (ví dụ: ngày giảm dần sau đó được sắp xếp theo thứ tự tăng dần) và mỗi cột hỗ trợ phân loại định hướng có hiệu quả gấp đôi số lượng các trường hợp. Vâng ... nó có lông rất nhanh.
Ý tưởng là người ta có thể "dễ dàng" thay đổi các trường hợp sắp xếp sao cho phương tiện được sắp xếp trước thời gian lưu trữ ... nhưng tính linh hoạt giả, ít nhất là trong ví dụ đơn giản này, thực sự kết thúc ở đó. Về cơ bản, mỗi trường hợp không thực hiện kiểm tra (vì phương pháp sắp xếp của chúng tôi không áp dụng cho lần này) sẽ hiển thị giá trị NULL. Và do đó, bạn kết thúc với một mệnh đề có chức năng như sau:
ORDER BY NULL DESC, NULL, [storagedatetime] DESC, blah blah
Bạn có được ý tưởng. Nó hoạt động vì SQL Server thực sự bỏ qua các giá trị null theo các mệnh đề. Điều này cực kỳ khó để duy trì, vì bất kỳ ai có bất kỳ kiến thức làm việc cơ bản nào về SQL đều có thể thấy. Nếu tôi mất bất kỳ ai trong số các bạn, đừng cảm thấy tồi tệ. Chúng tôi đã mất một thời gian dài để làm cho nó hoạt động và chúng tôi vẫn bối rối khi cố gắng chỉnh sửa nó hoặc tạo ra những cái mới như nó. Rất may, nó không cần thay đổi thường xuyên, nếu không nó sẽ nhanh chóng trở thành "không đáng để gặp rắc rối."
Tuy nhiên, nó đã làm việc.
Câu hỏi của tôi là: có cách nào tốt hơn không?
Tôi ổn với các giải pháp khác ngoài các giải pháp Thủ tục được lưu trữ, vì tôi nhận ra rằng nó có thể không phải là con đường để đi. Tốt hơn là, tôi muốn biết liệu có ai có thể làm điều đó tốt hơn trong Quy trình được lưu trữ hay không, nhưng nếu không, làm thế nào để bạn xử lý cho phép người dùng tự động sắp xếp các bảng dữ liệu (theo hai hướng) với ASP.NET?
Và cảm ơn bạn đã đọc (hoặc ít nhất là đọc lướt qua) một câu hỏi dài như vậy!
PS: Rất vui vì tôi đã không hiển thị ví dụ về quy trình được lưu trữ hỗ trợ sắp xếp động, lọc động / tìm kiếm văn bản của các cột, phân trang thông qua ROWNUMBER () QUÁ, và thử ... bắt lỗi với giao dịch quay lại lỗi ... "cỡ khổng lồ" thậm chí không bắt đầu mô tả chúng.
Cập nhật:
- Tôi muốn tránh SQL động . Phân tích một chuỗi với nhau và chạy EXEC trên chuỗi đó đánh bại rất nhiều mục đích của việc có một thủ tục được lưu trữ ở vị trí đầu tiên. Đôi khi tôi tự hỏi mặc dù những khuyết điểm của việc làm một việc như vậy sẽ không đáng, ít nhất là trong những trường hợp sắp xếp động đặc biệt này. Tuy nhiên, tôi luôn cảm thấy bẩn bất cứ khi nào tôi thực hiện các chuỗi SQL động như thế - giống như tôi vẫn đang sống trong thế giới ASP cổ điển.
- Rất nhiều lý do chúng tôi muốn các thủ tục được lưu trữ ở nơi đầu tiên là để bảo mật . Tôi không nhận được cuộc gọi về mối quan tâm bảo mật, chỉ đề xuất giải pháp. Với SQL Server 2005, chúng tôi có thể đặt quyền (trên cơ sở cho mỗi người dùng nếu cần) ở cấp lược đồ trên các quy trình được lưu trữ riêng lẻ và sau đó từ chối mọi truy vấn trực tiếp đối với các bảng. Phê bình những ưu và nhược điểm của phương pháp này có lẽ là cho một câu hỏi khác, nhưng một lần nữa, đó không phải là quyết định của tôi. Tôi chỉ là con khỉ mã chì. :)