在where子句中使用可选参数

时间:2017-02-22 11:32:03

标签: sql-server

我在存储过程中有以下示例查询,其中@StartDate,@ EndDate和@ClientID参数都是可选的。

在查询中处理该问题的最佳方法是什么,以确保根据1个或多个参数是否具有值来获得结果?

select * from table
WHERE
    StartDate >= @StartDate and
    StartDate <= @EndDate and
    CE.ClientID = @ClientID

例如,有人可以只输入开始日期或只输入结束日期或选择特定的ClientID或执行所有3的组合。

3 个答案:

答案 0 :(得分:1)

你可以这样做 -

SELECT * FROM table
WHERE
    (@StartDate IS NULL OR StartDate >= @StartDate) AND
    (@EndDate IS NULL OR StartDate <= @EndDate) AND
    (@ClientID IS NULL OR CE.ClientID = @ClientID)

答案 1 :(得分:1)

最好的方法是使用动态SQL。像这样:

declare @sql nvarchar(max);
set @sql = 'select * from table';

declare @where nvarchar(max);

set @where = (case when @StartDate is not null then ' and StartDate >= @StartDate' else '' end) +
             (case when @EndDate is not null then ' and EndDate >= @EndDate' else '' end) +
             (case when @ClientID is not null then ' and ClientID = @ClientID' else '' end);

set @where = stuff(@where, 1, 5, '');

set @sql = @sql + (case when len(@where) > 0 then ' where ' + @where' else '');

exec sp_executesql @sql,
                   N'@StartDate date, @EndDate date, @ClientId int',
                   @StartDate = @StartDate, @EndDate = @EndDate, @ClientId = ClientId;

这更好的原因是因为每个可能的输入组合导致不同的查询。 SQL Server可以使用适当的索引优化查询,这种优化在使用可选参数时非常重要。

答案 2 :(得分:1)

如果您愿意在每次执行时牺牲一小部分时间,OPTION(RECOMPILE)将提供与动态SQL相同的性能,但不会产生任何危险。

select * from table
WHERE
    (StartDate >= @StartDate or @StartDate is null) and
    (StartDate <= @EndDate or @EndDate is null) and
    (CE.ClientID = @ClientID or @ClientID is null)
option(recompile)