【问题标题】:Stored procedure bit parameter activating additional where clause to check for null存储过程位参数激活附加 where 子句以检查 null
【发布时间】:2010-09-14 05:32:47
【问题描述】:
我有一个如下所示的存储过程:
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 子句?感谢您的帮助。
【问题讨论】:
标签:
sql
stored-procedures
【解决方案1】:
这种做法往往会混淆查询优化器。我已经看到 SQL Server 2000 以完全相反的方式构建执行计划,并在设置标志时在 Column1 上使用索引,反之亦然。 SQL Server 2005 似乎至少在第一次编译时就获得了正确的执行计划,但是你遇到了一个新问题。系统缓存已编译的执行计划并尝试重用它们。如果您首先以一种方式使用查询,即使额外的参数发生变化,它仍然会以这种方式执行查询,并且不同的索引会更合适。
您可以通过在EXEC 语句中使用WITH RECOMPILE 或每次通过在CREATE PROCEDURE 语句中指定WITH RECOMPILE 来强制重新编译存储过程。 SQL Server 每次都会重新解析和优化查询,因此会受到惩罚。
一般来说,如果您的查询形式要改变,请使用带参数的动态 SQL 生成。 SQL Server 还将缓存参数化查询和自动参数化查询(它试图推断哪些参数是参数)甚至常规查询的执行计划,但它最重视存储过程执行计划,然后是参数化、自动参数化和按该顺序进行常规查询。权重越高,如果服务器需要内存来做其他事情,它在计划被丢弃之前在 RAM 中停留的时间就越长。
【解决方案2】:
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,则将评估列条件。
【解决方案3】:
select *
from SomeTable t
where t.Column1 is null
and (@AdditionalFilter = 0 or t.Column2 is not null)
【解决方案4】:
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)