存储过程-根据输入内容取消条件

时间:2018-08-21 10:36:55

标签: sql-server stored-procedures conditional

我有一个具有三个输入变量的存储过程:@ StartDate,@ EndDate)和@Type:

select t2.ID,
    t1.DESC  
from(select ID 
      from  [dbo].[RI]
       where [Date] between @StartDate and @EndDate) t2
       left join [dbo].[R] t1 on t2.ID = t1.ID
       where t1.DESC = @Type

问题是最后一个where条件。 T1.DESC始终具有三个可能的值之一(type1,type2或type3),但是在某些情况下,我想取消“ where-condition”,以便获得所有可能的值,就像未执行where-condition一样。如果@Type ='all',则取消该条件。有什么建议吗?

2 个答案:

答案 0 :(得分:0)

我会使用IF / ELSE结构,但是如果给出Type的实际参数值,它将调用动态SQL。使用带有两个正则sql表达式的IF / ELSE结构的问题是,优化器将在首次使用传入的参数运行过程时编译所有这些查询。因此,您需要立即解决参数嗅探问题。

不是这样,通过使用动态SQL,一旦击中IF语句的那一侧,优化器将为动态SQL创建一个不同的计划,假设如果您在两个单独的过程中运行查询,则计划将有所不同。

所以您的proc可能看起来像这样(我没有检查语法):

String

答案 1 :(得分:0)

因此t1.DESC可以包含type1type2type3之类的值。如果要省略过滤器,请使用OR来排除它。

WHERE
    @Type = 'all' OR t1.DESC = @Type

如果您的参数为all,则OR将始终返回 true ,因此不会按t1.DESC值进行过滤。如果不是all,则t1.DESC必须与@type匹配。

您还可以使用IS NULL来代替检查all这样的固定值,该值取决于您的口味。

如果这是一个复杂的查询,那么在末尾添加OPTION (RECOMPILE)可能很重要,因此考虑到参数的当前值,您迫使SQL引擎再次重新构建执行计划。使用WHERE过滤器存储执行计划与不使用过滤器存储执行计划是不一样的(这就是'all'的情况。)