检查不平等的有效方法

时间:2013-03-18 07:32:09

标签: sql sql-server

我正在编写一个正在执行的触发器

IF (@A <> @B)
    ...

但这不适用于@A或@B上的NULL值。它通常的方式是

IF (@A <> @B) OR (@A IS NOT NULL AND @B IS NULL) OR (@A IS NULL AND @B IS NOT NULL)

但这涉及最多9次比较而不是1次!

我能做到

SET ANSI_NULLS OFF

但显然不建议这样做(并且不推荐使用)。

那么最佳解决方案是什么?当它应该为1时,只需进行9次比较即可进行简单的不等式检查?触发器不是性能关键,但确实需要快速。批量加载时,这可能会大大减慢它的速度。

表演测试

以下是performance test的结果,它检查不等式一百万次,使得90%的时间值不相等,10%的时间每个值可能为空。

IF (@A <> @B) OR (@A IS NULL AND @B IS NOT NULL) OR (@A IS NOT NULL AND @B IS NULL)

结果:平均3848毫秒

IF (ISNULL(@A, 0) <> ISNULL(@B, 0)) 

结果:平均3942毫秒

IF (@A = @B) GOTO Equal ELSE IF @A IS NULL AND @B IS NULL GOTO Equal

结果:平均4140毫秒

IF EXISTS (SELECT @A EXCEPT SELECT @B)

结果:平均7795ms

时间并不重要,重要的是相对差异。显然,经典方法是最快的。可能的MSSQL内部针对此类检查进行了优化。

在MacBook Pro上运行测试(运行MSSQL 2008 Express的Vista VM中的Intel Core 2 Duo,2.4Ghz,8GB RAM)。

5 个答案:

答案 0 :(得分:7)

ANSI SQL有IS DISTINCT FROM但SQL Server中没有实现。它可以是simulated,不依赖于魔术常量,并且如果在列上使用则可以是sargable

IF EXISTS (SELECT @A EXCEPT SELECT @B)
     PRINT 'Different'

答案 1 :(得分:2)

在我看来,这是检查可空性并提供默认值的最佳方法。

IF ( ISNULL(@A, 0) <> ISNULL(@B, 0) )

一般语法

ISNULL ( check_expression , replacement_value )
  

如果不是NULL,则返回check_expression的值;   否则,在隐式地返回replacement_value   如果类型不同,则转换为check_expression的类型。   如果replacement_value超过,则replacement_value可以被截断   check_expression。

参考:MSDN - ISNULL

答案 2 :(得分:2)

您可以执行以下操作

ISNULL(@A,'N') <> ISNULL(@B,'N')

答案 3 :(得分:1)

以下是performance test的结果,它检查不等式一百万次,使得90%的时间值不相等,10%的时间每个值可能为空。

IF (@A <> @B) OR (@A IS NULL AND @B IS NOT NULL) OR (@A IS NOT NULL AND @B IS NULL)

结果:平均3848毫秒

IF (ISNULL(@A, 0) <> ISNULL(@B, 0)) 

结果:平均3942毫秒

IF (@A = @B) GOTO Equal ELSE IF @A IS NULL AND @B IS NULL GOTO Equal

结果:平均4140毫秒

IF EXISTS (SELECT @A EXCEPT SELECT @B)

结果:平均7795ms

时间并不重要,重要的是相对差异。显然,经典方法是最快的。可能的MSSQL内部针对此类检查进行了优化。

在MacBook Pro上运行测试(运行MSSQL 2008 Express的Vista VM中的Intel Core 2 Duo,2.4Ghz,8GB RAM)。

答案 4 :(得分:0)

我知道很多人不会喜欢这个,但因为表现是一个重要的问题,我正在使用它(除非有人有充分的理由)

IF @A = @B GOTO Equal ELSE IF @A IS NULL AND @B IS NULL GOTO Equal
NotEqual:
  PRINT 'Different'
Equal:

这要快得多,因为几乎总是@A和@B相等,只有1次比较。在少数情况下,当@ A和@B不相等时,需要进行1.5次平均比较才能确定不平等。

这是针对触发器中行更新的列级审核。比较@A和@B表示每个表的每次更新中每行中每列的“旧值”和“新值”。