2010-11-02 70 views
2

我已經研究了這個場景幾個小時,但似乎無法找到任何直接解決它的問題。SQL Server 2005 - WHERE子句 - 使用IF或CASE還是BOOLEAN?

我有很多可選參數傳遞到存儲過程。我想返回一個沒有過濾的記錄集,一個或多個傳入存儲過程的可選參數。

我正試圖產生一個單一的查詢來做到這一點。

這裏是我的僞碼(SQL Server 2005中):

declare @a varchar(10); set @a = null; 
declare @b varchar(10); set @b = 'comm%'; 

select * from x 
where (if @a is not null then col1 like @a) 
and (if @b is not null then col2 like @b) 

正如你可以看到我只想在col1 過濾如果我的參數(@a)的數據。同樣我只想過濾col2 if我的參數(@b)有數據。如果@a和@b都是NULL,那麼查詢應該返回所有行。

我發現幾個線程接近我想要的,但沒有一個地址使用LIKE子句。

回答

2
SELECT * FROM X WHERE (@a IS NULL OR col1 LIKE @a) AND (@b IS NULL OR col2 LIKE @b) 
+0

這解決了我的問題。非常感謝:) – Mark 2010-11-02 01:49:15

+0

@Mark。樂意效勞! – 2010-11-02 01:50:53

4

你接近 - 使用:

SELECT x.* 
    FROM X x 
WHERE (@a IS NULL OR x.col1 LIKE @a) 
    AND (@b IS NULL OR x.col2 LIKE @b) 

但這是not recommended because it's not sargableDynamic SQL將是一個更好的辦法:

DECLARE @SQL NVARCHAR(MAX) 
    SET @SQL = N'SELECT x.* 
        FROM X x 
        WHERE 1 = 1 ' 

    SET @SQL = @SQL + CASE 
         WHEN @a IS NULL THEN ' ' 
         ELSE ' AND x.col1 LIKE @a ' 
         END 

    SET @SQL = @SQL + CASE 
         WHEN @b IS NULL THEN ' ' 
         ELSE ' AND x.col2 LIKE @b ' 
         END 

BEGIN 

    EXEC sp_executesql @SQL, 
        N'@a VARCHAR(10), @b VARCHAR(10)', 
        @a, @b 

END 
+0

我的一些列將被編入索引,而另一些則不會。查詢執行的靈活性更重要,因此可控性並不會真正影響我的usp。但感謝您的反饋 - 我確信它會爲此話題的其他人提供幫助:) – Mark 2010-11-02 01:51:44

1

這可能是你要尋找的最有效的方式。如果傳遞給存儲過程的值不是NULL

CREATE PROCEDURE sproc_example 
@Col1 varchar(30) = NULL, 
@Col2 varchar(30) = NULL, 
@Col3 varchar(30) = NULL 
AS 
SELECT Col1, 
     Col2, 
     Col3 
FROM MyTable 
WHERE Col1 LIKE COALESCE(@Col1,Col1) AND 
     Col2 LIKE COALESCE(@Col2,Col2) AND 
     Col3 LIKE COALESCE(@Col3,Col3) 
+0

非常感謝您的意見。您的解決方案也是理想的,也適用於我。 – Mark 2010-11-02 01:57:17

+0

該解決方案僅適用於列不允許NULL的情況。否則,它不會返回正確的數據。 – 2010-11-03 15:51:48

+0

@G Matros嗯......怎麼這樣? – 2010-11-04 02:40:54