在这种特定情况下,SQL Server是否会持续短路?

时间:2011-04-26 05:56:09

标签: sql-server tsql

首先让我说我完全清楚sql server没有短路评估。如果因为执行计划而认为合适,那就可以了,但最好不要猜测。

我想知道是否可以在任何特定情况下强制使用null - 例如在此查询中动态加载所有客户

declare @customerId int

set @customerId = null
select * from customer where ( (@customerId Is Null) Or CustomerId=@customerId)

CustomerId是PK(int),不可为空

问题:在这种情况下,是否有人知道引擎是否总是选择左侧,或者我们是否确实最终检查每行的右侧是否有CustomerId = null。 我猜这不能保证工作,因为右侧可能“选择性较差”但我很好奇,如果sql服务器看到null并且知道在每种情况下这样使用左侧因为null声明。 我认为这最好是作为下面的案例stmt完成(如果你可以更好地查询下面的请求!)但我只是好奇这个案例用于学习目的,如果有人知道这里一致的内部行为。它适用于我的所有情况,但它也是一个主键,不可空,所以这可能是这总是有效的原因。如果它是一个可以为空的类型,那么右手边的选择性可能低于左边,我们现在处理的是另一种情况。

我在两个查询中的执行计划似乎都是一样的。

无论如何 - 这是一种更好的写作方式(如果可以,请加强)



declare @customerId  int
set @customerId = null

select * from Customer
where 

case 
    when @customerId is null then 1
end = 1

or 
case 
    when @customerId is not null then @customerId
    else -1
end = CustomerId

这里的想法是为动态sql提供变通方法 - 所以我只是想确保我知道所有情况。

谢谢!

2 个答案:

答案 0 :(得分:3)

这里的主要问题不是短路。

当SQL Server编译批处理

declare @customerId int

set @customerId = null
select * from customer where ( (@customerId Is Null) Or CustomerId=@customerId)

它没有做任何类型的“变量嗅探”,它考虑到前面的赋值语句,它只是将@customerId的值视为未知。

如果您使用的是某些版本的SQL Server 2008,则可以使用OPTION(RECOMPILE)让它在分配变量后重新编译该语句。

我建议您查看Dynamic Search Conditions in T-SQL

答案 1 :(得分:3)

你可以试试这个:

...WHERE CustomerId = COALESCE(@customerId, CustomerId)

或者,如果您愿意,可以使用“扩展”版本的COALESCE:

...WHERE CustomerId = CASE
                        WHEN @customerId IS NULL THEN CustomerId
                        ELSE @customerId
                      END