Как правильно реализовать MERGE для таблиц? Неверный результат CDC

Один раз в день один локальный SQL-сервер выполняет синхронизацию с каким-либо связанным сервером. Следующий запрос, использующий для слияния:

MERGE [TargetDb].[dbo].[TargetTable] AS Target
USING (SELECT * FROM [RemoteServer].[SourceDb].[dbo].[TestTable]) AS Source
    ON (Target.[ID] = Source.[ID])
WHEN MATCHED THEN
UPDATE SET  Target.[ID] = Source.[ID],
            Target.[TestFieldString] = Source.[TestFieldString],
            Target.[TestFieldInt] = Source.[TestFieldInt]
WHEN NOT MATCHED BY TARGET THEN
INSERT 
    (ID, TestFieldString, TestFieldInt) 
VALUES 
    (ID, Source.TestFieldString, Source.TestFieldInt);

Также на целевом сервере работает CDC (изменить сбор данных). Смотрит на CDC Статистика я обнаружил, что транзакция при обновлении не регистрируется в CDC, Следующий запрос для сбора статистики:

SELECT ch.*,  ch.__$seqval,
    CASE ch.__$operation
    WHEN 1 THEN 'delete'
    WHEN 2 THEN 'insert'
    WHEN 3 THEN 'prev val'
    ELSE 'new val' END  as operation,
    map.tran_begin_time, map.tran_end_time
FROM [cdc].[dbo_TestTable_CT] ch
    JOIN [cdc].[lsn_time_mapping] map
    ON ch.[__$start_lsn] = map.start_lsn
ORDER BY ch.__$start_lsn, ch.__$seqval

После нескольких тестов стало ясно. Это происходит с таблицами, которые содержат первичный ключ. Если исходная таблица с PK содержит изменения, тогда выполняется запрос Merge. DELETE а затем делать INSERT для каждого ряда.

Пример CDC следующий:

  1. Результат первого слияния в 1 ряд. Целевая таблица была пустой до этой операции.
  2. Обновление дляTestFieldString в исходной таблице и результат для второго слияния в 2 и 3 строки.
  3. Вставка новой записи в исходную таблицу и выполнение слияния. Результат для третьего слияния в 4,5,6 строки.

Это действительно странно. я жду prev val а также new val в колонке операций. Скрипт для создания этой таблицы выглядит следующим образом:

CREATE TABLE [dbo].[TestTable](
    [ID] [uniqueidentifier] NOT NULL PRIMARY KEY,
    [TestFieldString] [varchar](50) NULL,
    [TestFieldInt] [int] NULL
) ON [PRIMARY]
GO

Следующий результат CDC для аналогичной таблицы без первичного ключа.

  1. Результат первого слияния в 1 ряд. Целевая таблица была пустой до этой операции.
  2. Обновление дляTestFieldString в исходной таблице и слияния. Результат в 2 и 3 рядах.
  3. Вставка новой записи в исходную таблицу и слияние. Результат в 4 ряду.

Это правильно CDC результат для следующей таблицы:

CREATE TABLE [dbo].[TestTable](
    [ID] [uniqueidentifier],
    [TestFieldString] [varchar](50) NULL,
    [TestFieldInt] [int] NULL
) ON [PRIMARY]
GO

Я читал в MSD о MERGE, но не нашел описания для этой проблемы.

Как это исправить и что не так? Может быть, это ошибка или особенность MERGE пункт или CDC функциональность? Это особая проблема, но для функциональности, которую я разрабатываю, это очень важная проблема.

Кроме того, перед слиянием я пытался отключить ограничения в таблице, но получил ошибку, в которой говорилось, что CDC заблокировал ограничения. Может быть, есть возможность пометить ограничения (в моем случае это первичный ключ) перед объединением и после этого получить правильный результат CDC?

Также перед слиянием запускаю следующую СП:

exec sp_MSforeachtable @command1='ALTER TABLE ? NOCHECK CONSTRAINT ALL'

И после слияния:

exec sp_MSforeachtable @command1='ALTER TABLE ? CHECK CONSTRAINT ALL'

0 ответов

Другие вопросы по тегам