MERGE с UPSERT, не внося никакого значения в таблицу

Структура таблицы:

CREATE TABLE [dbo].[LockOfferByOfferUses](
[OfferID] [int] NULL,
[OfferCode] [varchar](50) NULL,
[LockCounter] [int] NULL,
[UpdatedDate] [datetime] NULL
) ON [PRIMARY]

SQL statemnt:

merge into LockOfferByOfferUses as Target
using (Select * from LockOfferByOfferUses Where OfferID=123 And OfferCode='abc' ) as Source
on Target.OfferID = Source.OfferID
when NOT MATCHED then
INSERT (OfferID,OfferCode,LockCounter,UpdatedDate) VALUES (123,'abc',1,GETDATE())
when MATCHED then 
update set Target.LockCounter=Target.LockCounter+1;

Что я пытаюсь сделать, это проверить, существует ли запись в "LockOfferByOfferUse" по offerID. Если он не существует, вставьте запись; Если существует, обновите столбец "LockCounter".

Часть обновления работает, но вставка не работает. Отображается сообщение "(затронуто 0 строк)". Нет сообщения об ошибке.

Был бы очень признателен за помощь.

3 ответа

Решение

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

Так должно быть что-то вроде:

merge into LockOfferByOfferUses as Target
using (VALUES(123)) as Source (OfferID)
on Target.OfferID = Source.OfferID
when NOT MATCHED then
INSERT (OfferID,OfferCode,LockCounter,UpdatedDate) VALUES (Source.OfferID,'abc',1,GETDATE())
when MATCHED then 
update set Target.LockCounter=Target.LockCounter+1;

(Это зависит от вас, где вы перемещаете другие значения в Source также, или просто иметь их в качестве литералов в INSERT - для более сложных запросов может потребоваться большее количество значений в нескольких местах).

Давайте прокомментируем ваш запрос, чтобы понять, что происходит:

Объединить в LockOfferByOfferUses в качестве цели

merge into LockOfferByOfferUses as Target

Исходный запрос данных, отфильтруйте только offerId=123

using (Select * from LockOfferByOfferUses Where OfferID=123 And OfferCode='abc' ) as Source

Условие сделать слияние

on Target.OfferID = Source.OfferID

когда у нас есть строка с и Id, который не существует в цели, мы вставляем новые данные

when NOT MATCHED then
INSERT (OfferID,OfferCode,LockCounter,UpdatedDate) VALUES (123,'abc',1,GETDATE())

Если у нас есть соответствующие данные, мы обновляем

when MATCHED then 
update set Target.LockCounter=Target.LockCounter+1;

Поэтому происходит то, что все идентификаторы из вашей исходной таблицы существуют в вашей целевой таблице, нет необходимости вставлять новые строки, виновник таков:

OfferID = 123

Вы всегда запрашиваете одно и то же значение, поэтому я предполагаю, что у вас есть пункт с OfferId 123 в качестве цели.

Исправленный запрос:

merge into LockOfferByOfferUses as Target
using (Select * from LockOfferByOfferUses Where OfferCode='abc' ) as Source
on Target.OfferID = Source.OfferID
when NOT MATCHED then
INSERT (OfferID,OfferCode,LockCounter,UpdatedDate) VALUES (123,'abc',1,GETDATE())
when MATCHED then 
update set Target.LockCounter=Target.LockCounter+1;

С помощью этого запроса вы бы слили все элементы с OfferCode abc, которые еще не завершены в целевой таблице.

Так как ваша таблица "Источник" пуста, нет ничего, чтобы соответствовать цели, и поэтому ничего не будет вставлено. Если вы хотите вставить данные, исходная таблица должна содержать строки для вставки.

ОБНОВЛЕНИЕ: Относительно вашего комментария: На самом деле есть два разных WHEN NOT MATCHED статьи: WHEN NOT MATCHED BY TARGET а также WHEN NOT MATCHED BY SOURCE, Но вы можете вставить только значения для WHEN NOT MATCHED BY TARGET пункт (который, кажется, по умолчанию). Но поскольку у вас нет исходных данных, вставлять нечего.

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