CASE
là một biểu thức trả về một giá trị. Nó không dành cho kiểm soát luồng, như IF
. Và bạn không thể sử dụng IF
trong một truy vấn.
Thật không may, có một số hạn chế với CASE
các biểu thức khiến bạn không thể làm được những gì bạn muốn. Ví dụ:tất cả các nhánh trong CASE
biểu thức phải trả về cùng kiểu hoặc có thể chuyển đổi hoàn toàn thành cùng kiểu. Tôi sẽ không thử điều đó với chuỗi và ngày tháng. Bạn cũng không thể sử dụng CASE
để chỉ định hướng sắp xếp.
SELECT column_list_please
FROM dbo.Product -- dbo prefix please
ORDER BY
CASE WHEN @sortDir = 'asc' AND @sortOrder = 'name' THEN name END,
CASE WHEN @sortDir = 'asc' AND @sortOrder = 'created_date' THEN created_date END,
CASE WHEN @sortDir = 'desc' AND @sortOrder = 'name' THEN name END DESC,
CASE WHEN @sortDir = 'desc' AND @sortOrder = 'created_date' THEN created_date END DESC;
Một giải pháp được cho là dễ dàng hơn (đặc biệt nếu điều này trở nên phức tạp hơn) là sử dụng SQL động. Để ngăn chặn SQL injection, bạn có thể kiểm tra các giá trị:
IF @sortDir NOT IN ('asc', 'desc')
OR @sortOrder NOT IN ('name', 'created_date')
BEGIN
RAISERROR('Invalid params', 11, 1);
RETURN;
END
DECLARE @sql NVARCHAR(MAX) = N'SELECT column_list_please
FROM dbo.Product ORDER BY ' + @sortOrder + ' ' + @sortDir;
EXEC sp_executesql @sql;
Một điểm cộng khác cho SQL động, bất chấp tất cả nỗi sợ hãi lan truyền về nó:bạn có thể có được kế hoạch tốt nhất cho từng biến thể sắp xếp, thay vì một kế hoạch duy nhất sẽ tối ưu hóa cho bất kỳ biến thể sắp xếp nào bạn đã sử dụng trước tiên. Nó cũng hoạt động tốt nhất trên toàn cầu trong một so sánh hiệu suất gần đây mà tôi đã chạy:
http://sqlperformance.com/conditional-order-by