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% の確率で各値が null である可能性があるなど、100 万回も不平等をチェックするパフォーマンス テストの結果です。

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 (Intel Core 2 Duo、2.4Ghz、MSSQL 2008 Express を実行する Vista VM 内の 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

私の意見では、これはnull可能性をチェックし、デフォルト値を提供するための最良の方法です。

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

一般的な構文

ISNULL ( check_expression , replacement_value )

check_expressionの値は、NULLでない場合に返されます。それ以外の場合、タイプが異なる場合は、replacement_valueが暗黙的にcheck_expressionのタイプに変換された後に返されます。replace_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% の確率で各値が null である可能性があるなど、100 万回も不平等をチェックするパフォーマンス テストの結果です。

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 (Intel Core 2 Duo、2.4Ghz、MSSQL 2008 Express を実行する Vista VM 内の 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 に答える