2009-11-17 94 views
2

我想創建一個存儲過程。如果參數是-1,那麼在該列上不應該有where子句,否則應該有WHERE子句。沒有大量IF分支的最好方法是什麼?SQL Server 2000存儲過程與參數分支

我檢查了存檔。有幾個類似的問題,但不完全相同。

CREATE PROCEDURE report 
(
    @site int, 
    @promo int, 
    @type int 
) 
AS 
SET NOCOUNT ON 

-- I want to avoid this: 
IF @site = -1 AND @promo = -1 and @type = -1 
BEGIN 
    SELECT * from table 
END 
IF @site > -1 AND @promo = -1 and @type = -1 
BEGIN 
    SELECT * from table WHERE site = @site; 
END 
... -- other cases 


ELSE -- all parameters are > -1 
BEGIN 
    SELECT * from table 
    WHERE site = @site AND promo = @promo AND type = @type 
END 

回答

3

在很多情況下(儘管評論會說不經過嘗試),因爲優化器會忽略ISNULL位,所以這種方法很有效。僅適用於非空列

SELECT @site = NULLIF(@site, -1) ... 

SELECT * from table 
    WHERE site = ISNULL(@site, site) .. 

否則,WHERE條件通常是不好的,因爲還是不能被優化

SELECT * from table 
    WHERE (@site = -1 OR site = @site) AND (... 

或者單獨的存儲過程(不認爲你想,要麼)

或者使用sp_executesql的(避免了動態SQL)

+1

用於NULLIF/ISNULL技巧的+1,以及用更好的答案更快地繪製。 – meklarian 2009-11-17 19:36:12

+1

我實施了第一個解決方案。耗時4秒。具有相同參數的第二種解決方案花費了2:40分鐘。表有三千萬行。 – Yada 2009-11-17 20:00:42

+0

@Yada:我有另一個轉換!人們認爲它不會擴大 – gbn 2009-11-17 20:03:43

1

如何:

SELECT * FROM table WHERE 
    ((site = @site) OR (@site = -1)) AND 
    ((promo = @promo) OR (@promo = -1)) AND 
    ((type = @type) OR (@type = -1)) 

但有一點需要注意,您可能會發現SQL在優化這類查詢方面並不是非常聰明。

1

爲什麼要對付明顯,最簡單的解決方案?

嚴重的是,分支解決方案意圖清晰,並且可以被其他人輕鬆理解。

+0

儘管在語句級別重新編譯中對SQL Server 2005更好地工作 – gbn 2009-11-17 18:54:05

+0

對於每列有2個選擇。所以2^3 = 8分支。 – Yada 2009-11-17 18:57:23