0

私は、システムから外部システムにデータを同期する必要があるプロジェクトに取り組んでいます。私が達成したいのは、カスタムクエリから変更されたアイテム (行) のみを定期的に送信することです。このクエリは次のようになります (ただし、さらに多くの列があります)。

SELECT T1.field1,
    T1.field2,
    T1.field2,
    T1.field3,
    CASE WHEN T1.field4 = 'some-value' THEN 1 ELSE 0 END,
    T2.field1,
    T3.field1,
    T4.field1
FROM T1
INNER JOIN T2 ON T2.pk = T2.fk
INNER JOIN T3 ON T3.pk = T2.fk
INNER JOIN T4 ON T4.pk = T2.fk

同期間ですべてのフィールドを 1 対 1 で比較する必要はありません。クエリからすべての行のハッシュを生成し、これを以前の同期からのハッシュと比較すると、変更された行のみが返されるという考えに至りました。私はCHECKSUM関数を認識していますが、衝突が非常に発生しやすく、時々変更を見逃す可能性があります。ただし、一時テーブルを作成して使用できる方法が気に入っていますCHECKSUM(*)。これにより、メンテナンスが簡単になります(クエリとチェックサムにフィールドを追加する必要はありません)。

SELECT T1.field1,
    T1.field2,
    T1.field2,
    T1.field3,
    CASE WHEN T1.field4 = 'some-value' THEN 1 ELSE 0 END,
    T2.field1,
    T3.field1,
    T4.field1
INTO #tmp
FROM T1
INNER JOIN T2 ON T2.pk = T2.fk
INNER JOIN T3 ON T3.pk = T2.fk
INNER JOIN T4 ON T4.pk = T2.fk;

-- get all columns from the query, plus a hash of the row
SELECT *, CHECKSUM(*)
FROM #tmp;

HASHBYTES関数 (衝突しにくい sha1、md5 をサポート) は知っていますが、列のリストや CHECKSUM のように * ではなく、varchar または varbinary のみを受け入れます。クエリからすべての列をキャスト/変換する必要があるのは面倒です...そしてエラーへの扉を開きます(たとえば、新しいフィールドを含めるのを忘れます)

また、SQL Server の変更データ キャプチャ機能と変更追跡機能にも気付きましたが、それらはすべて複雑で、私がやっていることにはやり過ぎのように思えます。

だから私の質問:私の基準を満たすクエリまたは一時テーブルからハッシュを生成する他の方法はありますか?

そうでない場合、この種の作業を達成する別の方法はありますか (クエリとの違いを同期するため)

4

1 に答える 1

1

FOR XML句のおかげで、私が望んでいたことを正確に行う方法を見つけました:

SELECT T1.field1,
    T1.field2,
    T1.field2,
    T1.field3,
    CASE WHEN T1.field4 = 'some-value' THEN 1 ELSE 0 END,
    T2.field1,
    T3.field1,
    T4.field1
INTO #tmp
FROM T1
INNER JOIN T2 ON T2.pk = T2.fk
INNER JOIN T3 ON T3.pk = T2.fk
INNER JOIN T4 ON T4.pk = T2.fk;

-- get all columns from the query, plus a hash of the row (converted in an hex string)
SELECT T.*, CONVERT(VARCHAR(100), HASHBYTES('sha1', (SELECT T.* FOR XML RAW)), 2) AS sHash
FROM #tmp AS T;
于 2013-11-12T19:06:49.943 に答える