2012-06-13 47 views
2

基本上我必須建立一個SQL數據庫的項目列表,但用戶可以選擇過濾7個過濾器的任何組合,也可以選擇一個列來排序,也可以按方向排序。排序,排序,過濾的複雜混合SQL Server

正如你可以想象的,這結束於大量不同的組合編碼和數據集是非常大的,所以我想避免在應用程序中這樣做。

在我的存儲過程到目前爲止,我曾嘗試:

建立一個查詢字符串,雖然這是非常簡單和容易執行,它離開開放的SQL注入的應用程序,所以我寧願避免這種情況。

我也嘗試使用一組IF ELSE語句來運行適當的參數化SQL,但是這很快就會變成一棵巨大的樹,並且將是一個噩夢來維護。

我不是第一個需要像這樣的解決方案的人,並且必須有比上述更好的方法嗎?另外作爲一個側面的問題,除了做大量的IF之外,還有一種很好的方式可以按照參數化的方式進行排序和排序?

+0

如果能減少過濾器'和(FLD1 = @過濾器1或@過濾器1爲空)'你應該閱讀http://www.sommarskog.se/dyn-search-2008.html –

回答

1

要進行篩選,請使用COELSCE按條件的任意組合進行篩選。在存儲過程中會有用戶會搜索所有參數的列表,然後在你的查詢將是這樣的:

SELECT * 
FROM YourTable t 
WHERE 1 = 1 
AND t.FirstColumn = COALESCE(@FirstColumnParam, t.FirstColumn) 
AND t.SecodndColumn = COALESCE(@SecondColumnParam, t.SecondColumn) 
.... 

如果任何參數爲空,則條件被跳過。併爲1=1這是萬一沒有過濾器coditions傳遞給您的查詢。

對於訂購:您可以使用CASE聲明任何choosen柱下令:

ORDER BY (CASE WHEN @OrderByParam = 1 Then FirstColumn ELSE .... END) 
+0

優化器是否會看到這是一個SARG並在使用COALESCE函數時使用索引? – buckley

+0

@buckley,不,我認爲它會創建索引,以防它寫入你寫的方式AND(FirstColumn = @FirstColumnParam或@FirstColumnParam爲NULL)' –

+0

@MahmoudGamal非常感謝,作品一種享受!有很多很好的SQL關鍵字,我可以隨時瞭解這些關鍵字! – radm4

1

建立一個查詢字符串,雖然這是非常簡單和容易 後續,它留下開放的SQL注入,所以我會 而避免這種情況的應用程序。

如果您使用sp_executesql,並將參數作爲參數傳遞給該sproc,則不適用。既然你給你的數據作爲參數不會有SQL注入

http://sqlinthewild.co.za/index.php/2009/04/03/dynamic-sql-and-sql-injection/

http://blogs.msdn.com/b/raulga/archive/2007/01/04/dynamic-sql-sql-injection.aspx

我還用一組if else語句然而,這運行適當 SQL參數化快速嘗試成爲一棵巨大的樹,並將是一個噩夢維持。

同意,如果您使用的if else,但也有一個叫捕捉模式的所有查詢

WHERE (ProductID = @Product Or @Product IS NULL) 
AND (ReferenceOrderID = @OrderID OR @OrderID Is NULL) 
... 

更多的信息在這裏http://sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries/

一定要在年底指定OPTION(RECOMPILE)因爲否則您的查詢可能會遭受所謂的參數嗅探

Also as a side question is there a good way to do order by and order by direction in a parameterised way, besides doing lots of IFs? 

Dynamic Sorting within SQL Stored Procedures

可能的複製,最後你可以用sp_executesql的或者捕獲所有查詢(這是一個常見的問題,這2試圖解決方案)。我通常prefere捕獲所有查詢,但不要忘記指定選項(重新編譯)。

+0

您無法將'where'子句作爲參數傳遞給'sp_executesql'。如果你動態地將SQL參數建立到'sp_executesql',那當然是對SQL注入開放的, – Andomar

+0

@Andomar我澄清了你必須將它們作爲參數傳遞給sproc的答案。我只是想要一個catch all選項重新編譯,這也將簡化動態排序 – buckley