我正在开发一个项目,我需要将数据从系统同步到外部系统。我想要实现的是定期从自定义查询中仅发送更改的项目(行)。此查询看起来像这样(但有更多列):
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
我想避免在同步之间一对一地比较每个字段。我的想法是,我可以为查询中的每一行生成一个哈希值,并将其与之前同步的哈希值进行比较,后者只返回已更改的行。我知道CHECKSUM函数,但它非常易于碰撞,有时可能会错过更改。但是我喜欢我可以制作临时表并使用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,它们不易发生冲突),但它只接受varchar或varbinary,而不是列表或* CHECKSUM的行。必须从查询中转换/转换每一列是一个痛苦...并打开错误的大门(例如,忘记包含一个新字段)
我还注意到了SQL Server的Change Data Capture and Change Tracking功能,但它们看起来都很复杂,而且我正在做的事情太过分了。
所以我的问题是:是否有另一种方法可以从符合我的标准的查询或临时表中生成哈希?
如果没有,还有其他方法可以实现这种工作(同步查询的差异)
答案 0 :(得分: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;