2009-11-17 96 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