2009-07-22 215 views
3

我有一個表中有很多字段。我正在嘗試在asp.net中創建搜索過濾器,以便用戶可以通過一個或多個字段的組合進行搜索。所以基本上我要創建一個存儲過程,發生在4個PARAMS,它會帕拉姆追加到WHERE子句如果不爲空...SQL篩選查詢

TableExample有4列中,col1 col2的COL3 COL4

我我希望有一種方法可以用單個存儲過程來完成,而不必爲每個可能的組合創建一個。

我正在嘗試這樣的事情,這是不正確的,但它迄今爲止得到的東西。

謝謝!

CREATE PROCEDURE [dbo].[Search] 
    @Col1 int, 
    @Col2 int, 
    @Col3 int, 
    @Col4 int 
AS 

SET TRANSACTION ISOLATION LEVEL READ COMMITTED 

SELECT * 

FROM 
    [dbo].[TestTable] 
WHERE 
    1=1 
    CASE   
     WHEN @Col1 IN NOT NULL 
     THEN AND [Col1] = @Col1 

     WHEN @Col2 IN NOT NULL 
     THEN AND [Col2] = @Col2 

     WHEN @Col3 IN NOT NULL 
     THEN AND [Col3] = @Col3 

     WHEN @Col4 IN NOT NULL 
     THEN AND [Col4] = @Col4 
    END 
+0

那麼什麼是共識,是它更好地只是建立在C#代碼方面的查詢字符串,然後做查詢,而不是試圖有一個存儲過程構建動態?存儲的proc方法似乎有一些缺陷...... – Gabe 2009-07-22 14:34:31

回答

0

我感謝大家的回覆。但是,我做了一些改變。我希望它能幫助別人!以下是我去一下吧:

CREATE PROCEDURE [dbo].[TestTable_Search] 
    @Col1 int, 
    @Col2 uniqueidentifier, 
    @Col3 datetime, 
    @Col4 datetime 
AS 

SET TRANSACTION ISOLATION LEVEL READ COMMITTED 

SELECT * 

FROM 
    [dbo].[TestTable] 
WHERE 
    [Col1] = COALESCE(@Col1, Col1) AND 
    [Col2] = COALESCE(@Col2, Col2) AND 
    [Col3] >= COALESCE(@Col3 + "00:00:00", Col3) AND 
    [Col4] <= COALESCE(@Col4 + "23:59:59", Col4) 
0

你不得不使用動態SQL來做到這一點:

CREATE PROCEDURE [dbo].[Search] 
    @Col1 int, 
    @Col2 int, 
    @Col3 int, 
    @Col4 int 
AS 

DECLARE @SQL nvarchar(MAX) 

SET TRANSACTION ISOLATION LEVEL READ COMMITTED 

SET @SQL = 'SELECT * 
       FROM [dbo].[TestTable] 
      WHERE 1=1 ' 

IF @Col1 IS NOT NULL 
SET @SQL = @SQL + ' AND Col1 = ''' + @Col1 + ''' ' 

IF @Col2 IS NOT NULL 
SET @SQL = @SQL + ' AND Col2 = ''' + @Col2 + ''' ' 

IF @Col3 IS NOT NULL 
SET @SQL = @SQL + ' AND Col3 = ''' + @Col3 + ''' ' 

IF @Col4 IS NOT NULL 
SET @SQL = @SQL + ' AND Col4 = ''' + @Col4 + ''' ' 

exec sp_executesql @SQL 

END 

記住,有危險這一點,包括SQL注入,以及其他權限問題的主機可能會出現,因爲它是動態SQL,但它是在數據庫層中完成此操作的唯一方法。如果您想在應用程序層(使用C#)構建查詢,則可以更徹底地抵禦SQL注入攻擊。

一些動態SQL鏈接,可以幫助您瞭解的弊端:

http://www.sommarskog.se/dynamic_sql.html http://slashstar.com/blogs/tim/archive/2006/10/12/The-Prevalence-and-Dangers-of-SQL-Injection.aspx

2

使用的事實,或短路。我假設-1不是一個有效的值。

CREATE PROCEDURE [dbo].[Search] 
    @Col1 int = -1, 
    @Col2 int = -1, 
    @Col3 int = -1, 
    @Col4 int = -1 
AS 
Begin 
SET TRANSACTION ISOLATION LEVEL READ COMMITTED 

SELECT * 

FROM 
    [dbo].[TestTable] 
WHERE 
(@Col1 = -1 OR [Col1] = @Col1) 
and 
(@Col2 = -1 OR [Col2] = @Col2) 
and 
(@Col3 = -1 OR [Col3] = @Col3) 
and 
(@Col4 = -1 OR [Col4] = @Col4) 



END 
+1

這也是我最喜歡搜索一段時間的方法。但後來我意識到它可能會對一些搜索參數很快導致糟糕的執行計劃和糟糕的性能。 – 2009-07-22 14:23:50

1

你可以用類似於你有什麼方法做到這一點:

WHERE 
    CASE 
    WHEN @Col1 IS NULL THEN true 
    ELSE [Col1] = @Col1 
    END 
AND 
    CASE 
    WHEN @Col2 IS NULL THEN true 
    ELSE [Col2] = @Col2 
    END 
... 

或者你可以把它簡單了很多,儘管可能不易閱讀:

WHERE (@Col1 IS NULL OR [Col1] = @Col1]) 
    AND (@Col2 IS NULL OR [Col2] = @Col2]) 
    AND ... 
2

搜索我鼓吹使用動態sql或在代碼中構建您的sql字符串的罕見選項之一。如果您擁有所有的sproc環境,請在您的sproc中使用動態sql。參數化並使用sp_executeSQL運行它以避免SQL注入