CASE
adalah ekspresi yang mengembalikan nilai. Ini bukan untuk kontrol aliran, seperti IF
. Dan Anda tidak dapat menggunakan IF
dalam kueri.
Sayangnya, ada beberapa batasan dengan CASE
ekspresi yang membuatnya rumit untuk melakukan apa yang Anda inginkan. Misalnya, semua cabang dalam CASE
ekspresi harus mengembalikan tipe yang sama, atau secara implisit dapat dikonversi ke tipe yang sama. Saya tidak akan mencobanya dengan string dan tanggal. Anda juga tidak dapat menggunakan CASE
untuk menentukan arah pengurutan.
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;
Solusi yang bisa dibilang lebih mudah (terutama jika ini menjadi lebih kompleks) adalah dengan menggunakan SQL dinamis. Untuk menggagalkan injeksi SQL, Anda dapat menguji nilainya:
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;
Kelebihan lain untuk SQL dinamis, terlepas dari semua ketakutan yang tersebar tentangnya:Anda bisa mendapatkan paket terbaik untuk setiap variasi jenis, alih-alih satu paket tunggal yang akan mengoptimalkan variasi jenis apa pun yang Anda gunakan terlebih dahulu. Ini juga berkinerja paling baik secara universal dalam perbandingan kinerja baru-baru ini yang saya jalankan:
http://sqlperformance.com/conditional-order-by