SQL Server Merge несколько вставок на не соответствует цели - PullRequest
0 голосов
/ 27 мая 2019

У меня есть две таблицы для слияния, одна - source , а другая - target .Данные в Source - это выходные данные CTE .

Я пытаюсь вставить данные в Target, но у меня есть два условия для вставки данных в таблицу назначения.

Я использую Merge для обновления существующих данных и вставки новой строки.Таблица целей включает в себя исторические данные.

Состояние в источнике будет равно 1 или 2, а состояние в цели будет либо R, либо S.

Вот пример процесса, который мне нужно выполнить.

Ниже приведены данные в исходной и целевой таблицах, а также несколько условий, которые мне нужно проверить.

Источник

| ID    |Name | Cond| Status |            
+-------+-----+-----+--------+
|   1   | A   | XYZ | 1      |

Target

| ID    |Name | Cond| Status |  cdate          
+-------+-----+-----+--------+
|   1   | A   | XYZ | R      | 4/09/2019 4:34:28

Условие 1: сейчас Если есть какие-то изменения в данных источника, то source.status = 2 и если target.id = source.id и target.status = 'R' тогда,цель должна быть обновлена ​​с исходными данными.

Источник

    | ID    |Name | Cond| Status |            
    +-------+-----+-----+--------+
    |   1   | B   | MNO | 2      |

Цель

    | ID    |Name | Cond| Status |   cdate         
    +-------+-----+-----+--------+
    |   1   | B   | MNO | R      | 4/09/2019 4:34:28

Условие 2: после выполнения одной хранимой процедуры, target.status изменено на 'S'.

Теперь, если target.status = 'S' и source.status = 2 и (target.name != source.name or target.cond != source.cond), новая строка должна быть вставлена ​​в цель с target.status как 'R'.

Источник

    | ID    |Name | Cond| Status |            
    +-------+-----+-----+--------+
    |   1   | B   | MNO | 2      |

Цель

    | ID    |Name | Cond| Status |            
    +-------+-----+-----+--------+
    |   1   | A   | XYZ | S      | 4/09/2019 4:34:28
    |   1   | B   | MNO | R      | 6/09/2019 7:34:28

Для достижения результата я использовал MERGE, как показано ниже:

MERGE table_1 AS TARGET
USING data_from_cte AS SOURCE ON (TARGET.ID = SOURCE.ID AND Target.status = 'R') 

--WHEN RECORDS ARE MATCHED, UPDATE THE RECORDS IF THERE IS ANY CHANGE
WHEN MATCHED AND TARGET.STATUS = 'R' 
    THEN UPDATE 
             SET TARGET.name = SOURCE.name,
                 TARGET.cond = SOURCE.cond,

--WHEN NO RECORDS ARE MATCHED, INSERT THE INCOMING RECORDS FROM SOURCE TABLE TO TARGET TABLE
WHEN MATCHED AND TARGET.STATUS = 'S' AND source.status = 2 
             AND (target.name != source.name OR target.cond != source.cond)
    THEN INSERT (id, name, cond, status) 
         VALUES (SOURCE.ID, SOURCE.name, SOURCE.cond, 'R')

WHEN NOT MATCHED BY TARGET 
    THEN INSERT (id, name, cond, status) 
         VALUES (SOURCE.ID, SOURCE.name, SOURCE.cond, 'R');

Проблема здесь: Я не могу сравнить целевой столбец и исходный столбец в WHEN MATCHED условии MERGE оператора.

Как решить эту проблему, используя оператор MERGE или оператор IF ... ELSE?

1 Ответ

1 голос
/ 28 мая 2019

Вы, кажется, довольно близко, там.Вы немного запутались, потому что вам нужно было проверить существование строки S с помощью exists, и вы попытались сделать это с помощью синтаксиса слияния.Это невозможно сделать: вы можете только INSERT на WHEN NOT MATCHED BY TARGET.Попробуйте это:

;MERGE table_1 AS TARGET
USING data_from_cte AS SOURCE -- (add WHERE source.status = 2 to your CTE)
ON (TARGET.ID = SOURCE.ID AND Target.status = 'R') 

--WHEN RECORDS ARE MATCHED, UPDATE THE RECORDS IF THERE IS ANY CHANGE
WHEN MATCHED AND TARGET.STATUS = 'R' AND operation='update' 
    THEN UPDATE 
             SET TARGET.name = SOURCE.name,
                 TARGET.cond = SOURCE.cond,

--WHEN NO RECORDS ARE MATCHED AND NO SAME S ROW EXISTS, INSERT THE INCOMING RECORDS FROM SOURCE TABLE TO TARGET TABLE
WHEN NOT MATCHED AND not exists(select 1 from table_1 t1 where t1.ID = SOURCE.ID AND t1.status = 'S' and t1.name = source.name and t1.cond = source.cond)
    THEN INSERT (id, name, cond, status) 
         VALUES (SOURCE.ID, SOURCE.name, SOURCE.cond, 'R')

Второе (WHEN NOT MATCHED ...) условие изменено, но также не забудьте добавить предложение WHERE source.status = 2 к вашему CTE

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...