存储过程 - 根据输入取消 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
可以包含 type1
、type2
或 type3
等值。如果您想省略过滤器,请使用 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' 会发生这种情况)。
我有一个包含三个输入变量的存储过程:@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
可以包含 type1
、type2
或 type3
等值。如果您想省略过滤器,请使用 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' 会发生这种情况)。