这些是我传递给存储过程的一些位值,并根据这些值生成了where子句
@booking bit,
@drs bit,
@manifest bit,
@receiving bit,
@status bit
非常简单
if (@booking=0)
Select * from Table where ColumnName='Booking'
if (@drs=1)
Select * from Table where ColumnName=DRS'
--so on based on other bit values
查询保持不变但基于位值我得到结果集并合并结果集。
在简单的一天,这个查询看起来像这个
Select * from Table where ColumnName in ('Booking','DRS')
我不想在我的存储过程中使用多个if语句,并且无论如何都要在单个查询中进行。
答案 0 :(得分:2)
您只需要在选项和OR
选项之间使用AND
语句,并使用启用它的位。
Select * from Table
where ( (ColumnName='DRS' AND @drs = 1)
OR (ColumnName='Booking' AND @booking = 1)
OR (ColumnName='Manifest' AND @manifest = 1)
OR (ColumnName='Receiving' AND @receiving = 1)
OR (ColumnName='Status' AND @status = 1)
)
正如Aaron在评论中指出的那样,这可能会影响您的表现,具体取决于查询计划的生成方式。
答案 1 :(得分:2)
另一个选项是动态SQL。它可以防止我提到的反对斯科特答案的问题:
请谨慎使用,因为您只会获得此模式的单个查询计划,并且根据ColumnName中值的偏差,它可能不是该作业的最佳查询计划。例如,如果表中出现“DRS”一次,并且表中出现“预订”600,000次,那么两个非常不同的计划可能对这些结果中的每一个都最有效......但是您将获得两个计划的计划将取决于首先生成的计划。
使用动态SQL,您可以使用optimize for ad hoc workloads
服务器设置(假设SQL Server 2008+)来防止缓存膨胀,您仍然可以使用OPTION (RECOMPILE)
击败参数嗅探。这是一个简单的例子:
DECLARE @sql NVARCHAR(MAX);
SET @sql = N'SELECT columns -- never use * in production
FROM dbo.Table -- always use schema prefix
WHERE ColumnName = @param OPTION (RECOMPILE);';
DECLARE @param VARCHAR(32);
SET @param = CASE WHEN @drs = 1 THEN 'DRS'
WHEN @booking = 1 THEN 'Booking'
WHEN @manifest = 1 THEN 'Manifest'
WHEN @receiving = 1 THEN 'Receiving'
WHEN @status = 1 THEN 'Status'
END;
EXEC sp_executesql @sql, N'@param VARCHAR(32)', @param;
维护起来更加丑陋,但是它更难以帮助你制定一个糟糕的计划(以及结果导致的糟糕表现)。