2008-09-30 107 views
4

我有一个存储过程,看起来像:存储过程位参数激活额外的where子句检查null

CREATE PROCEDURE dbo.usp_TestFilter 
    @AdditionalFilter BIT = 1 
AS 
    SELECT * 
    FROM dbo.SomeTable T 
    WHERE 
    T.Column1 IS NOT NULL 
    AND CASE WHEN @AdditionalFilter = 1 THEN 
     T.Column2 IS NOT NULL 

不用说,这是行不通的。如何激活检查@AdditionalFilter参数的附加where子句?谢谢你的帮助。

回答

6
CREATE PROCEDURE dbo.usp_TestFilter 
    @AdditionalFilter BIT = 1 
AS 
    SELECT * 
    FROM dbo.SomeTable T 
    WHERE 
    T.Column1 IS NOT NULL 
    AND (@AdditionalFilter = 0 OR 
     T.Column2 IS NOT NULL) 

如果@AdditionalFilter为0,该列将不能评价,因为它可以在不影响括号之间的部分的结果。如果它不是0,则列条件将被评估。

1
CREATE PROCEDURE dbo.usp_TestFilter 
    @AdditionalFilter BIT = 1 
AS 
    SELECT * 
    FROM dbo.SomeTable T 
    WHERE 
    T.Column1 IS NOT NULL 
    AND (NOT @AdditionalFilter OR T.Column2 IS NOT NULL) 
0
select * 
from SomeTable t 
where t.Column1 is null 
and (@AdditionalFilter = 0 or t.Column2 is not null) 
4

这种做法往往会混淆查询优化器。我已经看到SQL Server 2000完全相反地构建执行计划,并在设置标志时在Column1上使用索引,反之亦然。 SQL Server 2005似乎至少在第一次编译时获得了执行计划,但是随后出现了一个新问题。系统缓存编译的执行计划并尝试重用它们。如果您首先以某种方式使用查询,那么即使额外的参数发生更改,仍然会按照这种方式执行查询,并且不同的索引会更合适。

您可以强制在此执行重新编译存储过程通过在EXEC语句中使用WITH RECOMPILE,或通过在CREATE PROCEDURE语句中指定WITH RECOMPILE每次。由于SQL Server每次都重新分析和优化查询,因此将会受到惩罚。

通常,如果查询的格式将发生变化,请使用带参数的动态SQL生成。 SQL Server还将缓存参数化查询和自动参数化查询(它试图推断哪些参数是参数)的执行计划,甚至是常规查询,但它最重要的是存储过程执行计划,然后是参数化的,自动参数化的和按此顺序定期查询。权重越高,在计划被丢弃之前它可以留在RAM中的时间越长,如果服务器需要内存用于别的东西。