在没有主键但具有唯一字段的情况下检索CDC网络更改

时间:2018-07-18 13:45:44

标签: sql-server cdc

我想知道是否有可能检索类似于cdc.fn_cdc_get_net_changes_<capture_instance>(from_lsn , to_lsn, 'all with mask')的表的净变化,这些表没有主键,但确实有一个约束来确保一个(或多个)列是

1 个答案:

答案 0 :(得分:0)

花了我一段时间,但我认为我有一个可行的解决方案,请告诉我是否有更好的解决方案,或者您是否发现自己的错误。

我们假设一个名为capture_instance的表的捕获实例具有唯一列ID和非唯一列field1field2field3以及变量{ {1}}和@from_lsn

@to_lsn

要完全匹配WITH cdc_all AS ( -- Retrieve the change table with all changes SELECT * FROM cdc.fn_cdc_get_all_changes_capture_instance(@from_lsn, @to_lsn, 'all') ), f AS ( SELECT cdc_all.*, ops.[delete], ops.[insert], ops.[update], ops.[net_op] FROM cdc_all INNER JOIN ( -- Retrieve three flags for insert, update and delete and the net operation -- also filter insert + delete pairs because it results in no change SELECT * FROM ( SELECT ID , MAX(CASE WHEN __$operation = 1 THEN 1 ELSE 0 END) as [delete] , MAX(CASE WHEN __$operation = 2 THEN 1 ELSE 0 END) as [insert] , MAX(CASE WHEN __$operation = 4 THEN 1 ELSE 0 END) as [update] , MIN(__$operation) [net_op] FROM cdc_all GROUP BY ID ) ops WHERE NOT (ops.[delete] = 1 AND ops.[insert] = 1) ) ops ON cdc_all.ID = ops.ID ) SELECT net.[max_lsn], f.[net_op] __$operation , (CASE WHEN net.__$update_mask != 0x0 THEN net.__$update_mask ELSE NULL END) __$update_mask , f.[ID], [field1], [field2], [field3] FROM f INNER JOIN ( -- bitwise OR the __$update_mask of the updates -- also retrieve the last lsn of each row which should be used as the __$start_lsn of the result set SELECT ID , CAST(SUM(DISTINCT CAST((CASE WHEN f.[__$operation] = 4 AND f.[insert] != 1 THEN f.[__$update_mask] ELSE 0 END) as int)) as varbinary(2)) [__$update_mask] , MAX(__$start_lsn) [max_lsn] FROM f GROUP BY ID ) net ON f.ID = net.ID AND f.__$start_lsn = net.[max_lsn] 的行为,最后使varbinary的大小尽可能小,以使所有字段都适合,但是更大的值不会破坏功能。