存储过程 - 根据输入取消 where-condition

Stored procedure - cancel where-condition depending on input

我有一个包含三个输入变量的存储过程:@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 不是执行。 Fx 如果@Type = 'all' 条件应该被取消。有什么建议吗?

我会使用 IF/ELSE 结构,但如果给定了 Type 的实际参数值,则让它调用动态 SQL。使用带有两个正则 sql 表达式的 IF/ELSE 结构的问题在于,优化器将在程序第一次使用传入的参数 运行 时编译这两个查询。所以你是立即解决参数嗅探问题。

如果使用动态 SQL,则情况并非如此,优化器会在您点击 IF 语句的那一侧后为动态 SQL 创建一个不同的计划,假设如果您 运行 在两个单独的过程中进行查询。

所以你的过程看起来像这样(我没有检查语法):

IF @Type <> 'ALL'

EXEC sp_executesql N'
select t2.ID,
    t1.DESC  
from(select ID 
      from  [dbo].[RI]
       where [Date] between @StartDateParm and @EndDateParam) t2
       left join [dbo].[R] t1 on t2.ID = t1.ID
       where t1.DESC = @TypeParam', N'@StartDateParm datetime,@EndDateParam datetime,@TypeParam varchar(5)', 
       @StartDateParm = @StartDate, @EndDateParam = @EndDate, @TypeParam = @Type;

ELSE
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

因此 t1.DESC 可以包含 type1type2type3 等值。如果您想省略过滤器,请使用 OR 将其排除。

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

如果您的参数是 all,则 OR 将始终 return true,因此不会按 t1.DESC 值过滤.如果它不是 all 那么 t1.DESC 必须匹配 @type.

您也可以使用 IS NULL 而不是检查 all 等固定值,这取决于您的喜好。

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