SQL拼串功能強大,但是寫起來沒有提示不說,的確比較不太優雅,關鍵是拼串SQL將不得不接受性能上的巨大考驗和腳本注入的潛在威脅。所以,“探究”安全高效的SQL實現應該是每個程序員應盡的義務。^_^
create table # (data int,price int)
insert # select 1,2
insert # select 2,1
在SQL SERVER 2000中,通常是通過拼變量,然後使用EXEC執行的方法,或者採用臨時表的方法處理。在ORDER BY子句中,不允許使用變量!到了2005後,SQL SERVER 提供了ROW_NUMBER() 函數方法,這給我們進行分頁等需求提供了強大的支持。
DECLARE @a NVARCHAR(50)
SET @a=' data DESC '
SELECT * FROM [表名]
WHERE [條件]
ORDER BY @a
SELECT * FROM [表名]
WHERE [條件]
ORDER BY CASE @a WHEN ' data DESC ' THEN data DESC END
以上兩法是錯誤的,對於絕大多數人來說,剩下來的,就是拼串了。
DECLARE @OrderBy NVARCHAR(100)
SET @Sort =LOWER(LTRIM(RTRIM(@Sort )));
WITH _tempT AS(
SELECT * FROM [tab1],
CASE @sort
WHEN 'date desc' THEN ROW_NUMBER() OVER(ORDER BY data desc)
WHEN 'date asc' THEN ROW_NUMBER() OVER(ORDER BY data asc)
WHEN 'price desc' THEN ROW_NUMBER() OVER(ORDER BY price desc)
WHEN 'price asc' THEN ROW_NUMBER() OVER(ORDER BY price asc)
ELSE ROW_NUMBER() OVER(ORDER BY [data])
END AS RowNumber
WHERE [各種條件]
) SELECT * FROM _tempT
WHERE RowNumber between 1 and 100
ORDER BY RowNumber
ROW_NUMBER、RANK、DENSE_RANK 和 NTILE,這些新函數使您可以有效地分析數據以及向查詢的結果行提供排序值。您可能發現這些新函數有用的典型方案包括:將連續整數分配給結果行,以便進行表示、分頁、計分和繪製直方圖。
ROW_NUMBER
ROW_NUMBER 函數使您可以向查詢的結果行提供連續的整數值。ROW_NUMBER 總是按照請求的排序爲不同的行生成不同的行號。請注意,如果在 OVER() 選項中指定的 ORDER BY 列表不唯一,則結果是不確定的。這意味着該查詢具有一個以上正確的結果;在該查詢的不同調用中,可能獲得不同的結果。
新的排序函數的重要好處之一是它們的效率。SQL Server 的優化程序只需要掃描數據一次,以便計算值。它完成該工作的方法是:使用在排序列上放置的索引的有序掃描,或者,如果未創建適當的索引,則掃描數據一次並對其進行排序。另一個好處是語法的簡單性。
可以在行組內部獨立地計算排序值,而不是爲作爲一個組的所有錶行計算排序值。爲此,請使用 PARTITION BY 子句,並且指定一個表達式列表,以標識應該爲其獨立計算排序值的行組。
RANK, DENSE_RANK
RANK 和 DENSE_RANK 函數非常類似於 ROW_NUMBER 函數,因爲它們也按照指定的排序提供排序值,而且可以根據需要在行組(分段)內部提供。但是,與 ROW_NUMBER 不同的是,RANK 和 DENSE_RANK 向在排序列中具有相同值的行分配相同的排序。當 ORDER BY 列表不唯一,並且您不希望爲在 ORDER BY 列表中具有相同值的行分配不同的排序時,RANK 和 DENSE_RANK 很有用。RANK 和 DENSE_RANK 的用途以及兩者之間的差異可以用示例進行最好的解釋。
當 ORDER BY 列表不唯一時,ROW_NUMBER 是不確定的,而 RANK 和 DENSE_RANK 總是確定的。排序值和緊密排序值之間的差異在於,排序代表:具有較高得分的行號加 1,而緊密排序代表:具有明顯較高得分的行號加 1。從您迄今爲止已經瞭解的內容中,您可以推導出當 ORDER BY 列表唯一時,ROW_NUMBER、RANK 和 DENSE_RANK 產生完全相同的值。
NTILE
NTILE 使您可以按照指定的順序,將查詢的結果行分散到指定數量的組 (tile) 中。每個行組都獲得不同的號碼:第一組爲 1,第二組爲 2,等等。您可以在函數名稱後面的括號中指定所請求的組號,在 OVER 選項的 ORDER BY 子句中指定所請求的排序。組中的行數被計算爲 total_num_rows / num_groups。如果有餘數 n,則前面 n 個組獲得一個附加行。因此,可能不會所有組都獲得相等數量的行,但是組大小最大隻可能相差一行。
SELECT speaker, track, score,
ROW_NUMBER() OVER(ORDER BY score DESC) AS rownum,
NTILE(3) OVER(ORDER BY score DESC) AS tile
FROM SpeakerStats
ORDER BY score DESC
以下爲結果集:
speaker track score rownum tile
---------- ---------- ----------- ------ ----
Jessica Dev 9 1 1
Ron Dev 9 2 1
Suzanne DB 9 3 1
Kathy Sys 8 4 1
Michele Sys