CASE
是一个返回值的表达式。它不是为了控制流量,例如IF
。而且你不能使用IF
在查询中。
不幸的是,有一些限制CASE
使做你想做的事情变得很麻烦的表达方式。例如,a 中的所有分支CASE
表达式必须返回相同的类型,或者可以隐式转换为相同的类型。我不会尝试使用字符串和日期。你也不能使用CASE
指定排序方向。
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;
一个可以说更简单的解决方案(特别是当这变得更复杂时)是使用动态 SQL。要阻止 SQL 注入,您可以测试这些值:
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;
动态 SQL 的另一个优点是,尽管有很多关于它的散布恐惧的说法:您可以获得每种排序变体的最佳计划,而不是一个针对您首先使用的排序变体进行优化的单一计划。在我最近进行的性能比较中,它也普遍表现最佳:
http://sqlperformance.com/conditional-order-by http://sqlperformance.com/conditional-order-by