Мой SQL-запрос выглядит следующим образом:
IF OBJECT_ID('tempdb..#OutputIds') IS NOT NULL DROP TABLE #OutputIds;
CREATE TABLE #OutputIds (Action NVARCHAR(10), ChildId NVARCHAR(MAX));
MERGE INTO LeadShirts AS target
USING (VALUES ('abc', 'abc'), ('abc', 'abc')) AS source (ParentId, ChildId)
ON (target.Lead = source.ParentId AND target.Shirts = source.ChildId)
WHEN MATCHED AND target.Deleted = 1 THEN
UPDATE SET UpdatedOn = GETDATE(), Deleted = 0 -- Re-activate deleted records
OUTPUT 'Edited', source.ChildId INTO #OutputIds (Action, ChildId)
WHEN NOT MATCHED BY TARGET THEN
INSERT (Lead, Shirts, Deleted, CreatedOn)
VALUES (source.ParentId, source.ChildId, 0, GETDATE())
OUTPUT 'Added', source.ChildId INTO #OutputIds (Action, ChildId);
INSERT INTO #OutputIds (Action, ChildId)
SELECT 'Skipped', ChildId
FROM (VALUES ('abc', 'abc'), ('abc', 'abc')) AS V(ParentId, ChildId)
WHERE EXISTS (SELECT 1 FROM LeadShirts AS T WHERE T.Lead = V.ParentId AND T.Shirts = V.ChildId AND T.Deleted IS NULL);
SELECT Action, ChildId FROM #OutputIds;
И я продолжаю получать эту ошибку, когда запускаю ее на SQL Server:
Сообщение 156, уровень 15, состояние 1, строка 11
Неправильный синтаксис рядом с ключевым словом «WHEN».
Любое решение будет высоко оценено.
Синтаксис (VALUES( ... ) ) AS alias ( colA, colB ) ISO SQL достаточно неуклюж сам по себе, поэтому использование его внутри оператора MERGE просто вызывает раздражение... Я предлагаю вам перенести их либо в table-variables/temp-tables, либо в CTE.
@Дай - я не согласен. Его использование в MERGE — одно из наименее раздражающих мест. Если вы переместите его в CTE, это станет более раздражающим, поскольку вы не можете просто использовать его непосредственно в качестве определения выражения CTE, но вам нужно добавить из него SELECT.
Postgres позволяет использовать его прямо здесь dbfiddle.uk/lSmUNsPz


Как указано в комментарии @martin-smith, MERGE имеет только одно предложение OUTPUT в конце выражения: <output_clause>
Ошибка, с которой вы столкнулись, связана с тем, что SQL запутан: если OUTPUT стоит только в конце, то что пытается сделать следующее ключевое слово WHEN? Ответ от SQL правильный, incorrect syntax near the keyword 'WHEN'
Вместо этого это должно сработать, хотя в выводе меньше деталей:
IF OBJECT_ID('tempdb..#OutputIds') IS NOT NULL DROP TABLE #OutputIds;
CREATE TABLE #OutputIds (Action NVARCHAR(10), ChildId NVARCHAR(MAX));
MERGE INTO LeadShirts AS target
USING (VALUES ('abc', 'abc'), ('abc', 'abc')) AS source (ParentId, ChildId)
ON (target.Lead = source.ParentId AND target.Shirts = source.ChildId)
WHEN MATCHED AND target.Deleted = 1 THEN
UPDATE SET UpdatedOn = GETDATE(), Deleted = 0 -- Re-activate deleted records
WHEN NOT MATCHED BY TARGET THEN
INSERT (Lead, Shirts, Deleted, CreatedOn)
VALUES (source.ParentId, source.ChildId, 0, GETDATE())
OUTPUT $action, source.ChildId INTO #OutputIds (Action, ChildId);
-- Change the action message for deleted
UPDATE #OutputIds
SET Action = 'Edited'
WHERE Action = 'DELETE';
-- Change the action message for inserted
UPDATE #OutputIds
SET Action = 'Added'
WHERE Action = 'INSERT';
INSERT INTO #OutputIds (Action, ChildId)
SELECT 'Skipped', ChildId FROM (VALUES ('abc', 'abc'), ('abc', 'abc')) AS V(ParentId, ChildId)
WHERE EXISTS (SELECT 1 FROM LeadShirts AS T WHERE T.Lead = V.ParentId AND T.Shirts = V.ChildId AND T.Deleted IS NULL);
SELECT Action, ChildId FROM #OutputIds;
Надеюсь, это поможет объяснить, как работает MERGE и как можно манипулировать выводом, чтобы он соответствовал вашим критериям, если это действительно так важно;)
Не забывайте об обязательном ОБЪЕДИНЕНИИ HOLDLOCK ;)
@Дай, это хороший совет, хотя я не хочу добавлять его сюда, он немного не по теме, и я не хочу торчать и объяснять, почему он полезен и когда вы не будете его использовать. Однако этот чат должен посеять идею ;)
Кажется предпочтительнее использовать CASE $action WHEN 'UPDATE' THEN 'Edited' WHEN 'INSERT' THEN 'Added' END, чтобы вставить нужную строку напрямую, а не вставлять нежелательную, а затем обновлять ее.
Абсолютно, если нужно внести лишь небольшое количество изменений, я бы принял этот пиар;) Я только демонстрировал, что это можно сделать, поэтому выбрал подход первых принципов. Если у ОП возникают проблемы с документацией по MERGE, я не хочу вводить слишком много концепций.
У вас может быть только одно предложение
OUTPUT .. INTO, и оно находится в определенном месте. Ни одного за действие