Вы не можете сделать это напрямую с помощью оператора merge
, но есть простое решение.
Предложение merge
<merge_not_matched>
(которое является insert...values|default values
) может содержать только одну строку в целевой таблице для каждой строки в исходной таблице.
Это означает, что для ввода двух строк для каждого соответствия вам просто нужно изменить исходную таблицу - в этом случае это так же просто, как запрос перекрестного соединения.
Однако предложение <merge_matched>
требует, чтобы только одна строка из источника могла соответствовать любой отдельной строке из целевого объекта, иначе вы получите следующую ошибку:
Оператор MERGE пытался ОБНОВИТЬ или УДАЛИТЬ одну и ту же строку более одного раза. Это происходит, когда целевая строка соответствует более чем одной исходной строке. Оператор MERGE не может ОБНОВИТЬ / УДАЛИТЬ одну и ту же строку целевой таблицы несколько раз. Уточните предложение ON, чтобы убедиться, что целевая строка соответствует не более чем одной исходной строке, или используйте предложение GROUP BY для группировки исходных строк.
Чтобы решить эту проблему, вам нужно будет добавить условие к when match
, чтобы убедиться, что только одна строка из исходной таблицы обновляет целевую таблицу:
MERGE Items AS T
USING (
SELECT Id, Text, GetDate() As Date, IsNew
FROM @table
-- adding one row for each row in source
CROSS JOIN (SELECT 0 As IsNew UNION SELECT 1) AS isNewMultiplier
) AS S
ON T.[ID]=S.ID
WHEN MATCHED AND S.IsNew = 1 THEN -- Note the added condition here
UPDATE SET
T.[Content] = S.[Text]
WHEN NOT MATCHED THEN
INSERT (Id, Content, Time, IsNew) VALUES
(Id, Text, Date, IsNew);
Вы можете увидеть живое демо на rextester.
Учитывая все вышесказанное, я хотел бы отослать вас к другому сообщению stackoverflow , которое предлагает лучшую альтернативу, чем использование оператора merge
.
Автором ответа является Microsoft MVP и эксперт по базам данных SQL Server, вам следует хотя бы прочитать то, что он говорит.