4

我正在写一个正在做的触发器

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 次比较即可进行简单的不等式检查?触发器不是性能关键,但它确实需要快速。批量加载时,这可能会大大减慢速度。

性能测试

这是一个性能测试的结果,该测试检查了一百万次是否不相等,因此 90% 的时间值不相等,10% 的时间每个值可能为空。

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

结果:平均3848ms

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

结果:平均 3942ms

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

结果:平均 4140ms

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

5 回答 5

7

ANSI SQL 有IS DISTINCT FROM,但在 SQL Server 中没有实现。它可以以一种不依赖于魔法常数的方式进行模拟,并且如果在列上使用它是 sargable

IF EXISTS (SELECT @A EXCEPT SELECT @B)
     PRINT 'Different'
于 2013-03-18T07:44:37.900 回答
2

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

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

一般语法

ISNULL ( check_expression , replacement_value )

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

参考:MSDN - ISNULL

于 2013-03-18T07:42:28.613 回答
2

你可以做以下

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

于 2013-03-18T07:43:10.463 回答
1

这是一个性能测试的结果,该测试检查了一百万次是否不相等,因此 90% 的时间值不相等,10% 的时间每个值可能为空。

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

结果:平均3848ms

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

结果:平均 3942ms

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

结果:平均 4140ms

IF EXISTS (SELECT @A EXCEPT SELECT @B)

结果:平均 7795ms

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

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

于 2013-03-19T01:25:54.597 回答
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 表示每个表的每次更新中每一行中每一列的“旧值”和“新值”。

于 2013-03-18T09:13:41.453 回答