CASE
値を返す式です。 IF
のようなフロー制御用ではありません 。また、IF
は使用できません クエリ内。
残念ながら、CASE
にはいくつかの制限があります やりたいことをやるのが面倒な表現。たとえば、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