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
пункт (который, кажется, по умолчанию). Но поскольку у вас нет исходных данных, вставлять нечего.