在Transact-SQL中,比较两个可以为0、1或NULL的位值的最佳方法是什么?
例如,在使用参数值更新位列的存储过程中,我只想在参数值与表中的值不同时执行更新(表和参数中的值可以为0、1或NULL)。
我正在考虑:
WHERE …
AND (CASE WHEN b=@b OR COALESCE(b,@b) IS NULL THEN 0 ELSE 1 END) = 1
vs。
WHERE …
AND EXISTS (SELECT b EXCEPT SELECT @b)
是否有充分的理由偏爱一个?有一个更好的方法吗?
在这种情况下,只有一行会被更新,因此我认为性能不是大问题,除非有很大的不同。
答案 0 :(得分:1)
由于要比较的数据是可为空的bit
值,因此您可以使用Coalesce( B, -1 ) = Coalesce( @B, -1 )
对所有三个值(0
,1
和NULL
)进行匹配通过将它们映射到0
,1
和-1
。
Coalesce
遵循data type precedence的规则。给定一个bit
(B
)和一个int
(-1
),它将把bit
转换为int
,因此结果是int
值。
表达式不是SARGable,但是在这种情况下,OP声明正在对已经由PK标识的单行执行操作,因此比较的性能并不重要。
请注意,这是在原始数据的数据类型(-1
)中引入不能出现的值(bit
)的情况。它与选择可能不会发生的任意魔术值不同,例如1800
年过去太遥远,以至于无法在DateSold
列中出现。除了房地产和其他各种东西。
奖金提示:
一种方便的确认行为的方法是使用SQL_Variant_Property
显示结果的数据类型:
declare @B as Bit = 1;
select SQL_Variant_Property( Coalesce( @B, -1 ), 'BaseType' );