0

这些是我传递给我的存储过程的一些位值,并基于这些值生成我的 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 语句,并以任何方式在单个查询中进行。

4

2 回答 2

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 在评论中指出的那样,这可能会损害您的性能,具体取决于查询计划的生成方式。

于 2013-10-26T15:31:04.690 回答
2

另一种选择是动态 SQL。它可以防止我提到的针对斯科特的回答的问题:

请谨慎使用,因为您只会获得此模式的单个查询计划,并且根据 ColumnName 中值的偏差,它可能不是最适合该作业的查询计划。例如,如果“DRS”在表格中出现一次,而“Booking”在表格中出现 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;

它更丑陋,更难维护,但它让你坚持一个糟糕的计划的可能性要小得多(结果是一系列糟糕的表现)。

于 2013-10-26T17:13:03.587 回答