与UPSERT合并,不在表中插入任何值

时间:2016-08-25 09:04:58

标签: sql-server 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;

我要做的是,检查offerID是否存在“LockOfferByOfferUse”中的记录。如果它不存在,请插入记录;如果存在更新“LockCounter”列。

更新部分有效,但插入无效。它显示消息“(0行(s)受影响)”。没有错误消息。

真的很感激一些帮助。

3 个答案:

答案 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中的文字 - 对于更复杂的查询,更多的是在多个地方也可能需要这些值。)

答案 1 :(得分:1)

因为你的"来源" table为空,没有任何东西可以匹配目标,因此不会插入任何内容。如果要插入数据,源表必须包含要插入的行。

更新:关于您的评论:实际上有两个不同的WHEN NOT MATCHED BY TARGET条款:WHEN NOT MATCHED BY SOURCEWHEN NOT MATCHED BY TARGET。但是您只能插入--save=dev子句的值(这似乎是默认值)。但由于您没有任何源数据,因此无需插入任何内容。

答案 2 :(得分:1)

让我们对您的查询发表评论,以了解正在发生的事情:

将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;

因此,正在进行的是源表中的所有Id都存在于目标表中,无需插入新行,罪魁祸首是:

  

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的元素。