4

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

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

4 回答 4

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,则将评估列条件。

于 2008-09-30T10:44:57.073 回答
3

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

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

一般来说,如果您的查询形式要改变,请使用带参数的动态 SQL 生成。SQL Server 还将缓存参数化查询和自动参数化查询(它试图推断哪些参数是参数)甚至常规查询的执行计划,但它最重视存储过程执行计划,然后是参数化、自动参数化和按该顺序进行常规查询。权重越高,如果服务器需要内存来做其他事情,它在计划被丢弃之前在 RAM 中的停留时间就越长。

于 2008-09-30T12:06:04.227 回答
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)
于 2008-09-30T10:44:32.627 回答
0
select *
from SomeTable t
where t.Column1 is null
and (@AdditionalFilter = 0 or t.Column2 is not null)
于 2008-09-30T10:44:54.217 回答