我有一个看起来像的存储过程:
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子句?谢谢你的帮助。
答案 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)