У меня есть целевая таблица, содержащая элементы с флагом IsActive
, и я вставляю и обновляю исходную таблицу с помощью инструкции MERGE
. Если что-то существует в исходной таблице, то оно активно, а если нет, то оно не активно. Логика довольно проста:
- если он существует в источнике и цели, строка должна иметь
IsActive
true - если он существует только в источнике, тогда в цель должна быть добавлена новая строка с
IsActive
true - если он существует только в целевой, тогда
IsActive
должен быть установлен в false.
Все очень просто, за исключением того, что целевая таблица также имеет различающийся столбец SourceId
, который относится к исходной таблице. Поэтому для данной исходной таблицы я хочу только MERGE
от строк с соответствующим SourceId
.
(Моя нормализованная таблица содержит строки одинаковых типов данных из нескольких систем - я извлекаю данные из этих систем отдельно и, следовательно, необходимо объединить из одного источника за раз)
Вот пример:
IF OBJECT_ID('tempdb..#target') IS NOT NULL DROP TABLE #target
IF OBJECT_ID('tempdb..#source') IS NOT NULL DROP TABLE #source
CREATE TABLE #target ( Id INT, SourceId INT, IsActive BIT )
INSERT #target VALUES (1, 1, 0)
INSERT #target VALUES (2, 1, 1)
INSERT #target VALUES (3, 2, 1)
CREATE TABLE #source ( Id INT )
INSERT #source VALUES (1)
INSERT #source VALUES (4)
DECLARE @SourceId INT = 1;
SELECT * FROM #target
MERGE INTO #target t
USING
(
SELECT [Id] FROM #source
) AS s
ON t.[Id] = s.[Id] AND t.[SourceId] = @SourceId
WHEN MATCHED THEN UPDATE SET [IsActive] = 1
WHEN NOT MATCHED BY TARGET THEN INSERT VALUES ([Id], @SourceId, 1)
WHEN NOT MATCHED BY SOURCE THEN UPDATE SET [IsActive] = 0;
SELECT * FROM #target
Моя первоначальная попытка состояла в том, чтобы включить AND t.[SourceId] = @SourceId
в условие слияния, но, очевидно, это не сработает - оно ограничивает элементы для объединения, но не целевую таблицу. Целевая строка ID = 3 не будет соответствовать, и поэтому она будет установлена в неактивную, независимо от того, включено ли это дополнительное условие.
Конечным результатом является то, что всякий раз, когда процедура запускается для исходной системы, все остальные системы будут установлены как неактивные.
Мое решение до сих пор заключается в том, чтобы запустить MERGE
только для MATCHED
и NOT MATCHED BY TARGET
, а затем запустить следующий UPDATE
для непревзойденных строк
UPDATE #target
SET [IsEnabled] = 0
WHERE [SourceId] = @SourceId
AND [ID] NOT IN (SELECT [ID] FROM #source)
Можно ли включить это условие фильтра в оператор MERGE
? Есть ли какие-нибудь другие умные способы достичь этого?