存储过程位参数激活附加where子句以检查null

时间:2008-09-30 10:40:48

标签: sql stored-procedures

我有一个看起来像的存储过程:

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子句?谢谢你的帮助。

4 个答案:

答案 0 :(得分: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 :(得分:4)

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

您可以使用WITH RECOMPILE语句中的EXEC或每次在WITH RECOMPILE语句中指定CREATE PROCEDURE来强制在此次执行时重新编译存储过程。每次SQL Server重新解析并优化查询时都会受到惩罚。

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

答案 2 :(得分: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)

答案 3 :(得分:0)

select *
from SomeTable t
where t.Column1 is null
and (@AdditionalFilter = 0 or t.Column2 is not null)