存储过程中的可选参数 - CASE与OR

时间:2009-09-11 16:42:16

标签: sql sql-server tsql

这些过滤方法之间的性能是否存在差异?

Method 1: WHERE (@Col1 IS NULL OR t.column = @Col1) 


Method 2: WHERE 1 = case when @col1 is null then 1 else case when col1 = @col1 then 1 else 0 end end

3 个答案:

答案 0 :(得分:2)

为什么不使用Coalesce?

Where Col1 = Coalesce(@Col1, Col1)

编辑:(请参阅下面的Joel评论)仅当col1不允许Null时,或者如果它允许空值并且您希望在@ Col1为空或不存在时排除空值,则此方法有效。因此,如果它允许空值,并且当@ Col1参数为空或不存在时,您希望它们 包含 ,则修改如下:

 Where Coalesce(@Col1, Col1) Is Null Or Col1 = Coalesce(@Col1, Col1)  

答案 1 :(得分:2)

如果您知道Col1列本身不包含任何空值,则可以执行以下操作:

WHERE Col1 = COALESCE(@Col1, Col1)

否则,您的CASE语句通常比OR好一点。我强调“典型”,因为表格不同。你应该总是知道如何确定。

不幸的是,通常最快的方式是使用动态sql,如果参数为null,则首先从查询中排除条件。但当然可以将其视为最后的优化。

答案 2 :(得分:2)

是。 CASE具有保证的执行顺序,而OR则没有。许多程序员依赖于OR短路,并且惊讶地发现像SQL这样的面向集合的声明性语言并不能保证布尔运算符的短路。

在WHERE子句中使用OR和CASe说是不好的做法。将条件分成清晰的IF语句,并在每个分支上分别进行查询:

IF @col1 IS NOT NULL
  SELECT ... WHERE col1 = @col1;
ELSE
  SELECT ... WHERE <alternatecondition>;

将条件置于WHERE内部通常会使优化器无法猜测@ col1将会是什么,并产生涉及完整扫描的错误计划。

<强>更新

由于我厌倦了一次又一次地解释在SQL中无法保证布尔短路,我决定写一篇关于它的完整博客专栏:SQL Server boolean operator short-circuit。在那里你会发现一个简单的计数器示例,显示布尔短路不仅无法保证,而依赖它实际上可能非常危险,因为它可能导致< strong>运行时错误。