Sql server SQL Server中单行合并/升级插入的语法

Sql server SQL Server中单行合并/升级插入的语法,sql-server,merge,upsert,Sql Server,Merge,Upsert,我正在尝试对一个表执行单行插入/更新,但是所有的示例都是针对集合的 有人可以修改我的语法吗 MERGE member_topic ON mt_member = 0 AND mt_topic = 110 WHEN MATCHED THEN UPDATE SET mt_notes = 'test' WHEN NOT MATCHED THEN INSERT (mt_member, mt_topic, mt_notes) VALUES (0, 110, 'test') 每个marc_s的分辨率是将单行

我正在尝试对一个表执行单行插入/更新,但是所有的示例都是针对集合的

有人可以修改我的语法吗

MERGE member_topic ON mt_member = 0 AND mt_topic = 110
WHEN MATCHED THEN UPDATE SET mt_notes = 'test'
WHEN NOT MATCHED THEN INSERT (mt_member, mt_topic, mt_notes) VALUES (0, 110, 'test')
每个marc_s的分辨率是将单行转换为子查询-这使我认为MERGE命令实际上不适用于单行UPSERT

MERGE member_topic
USING (SELECT 0 mt_member, 110 mt_topic) as source
ON member_topic.mt_member = source.mt_member AND member_topic.mt_topic = source.mt_topic
WHEN MATCHED THEN UPDATE SET mt_notes = 'test'
WHEN NOT MATCHED THEN INSERT (mt_member, mt_topic, mt_notes) VALUES (0, 110, 'test');

基本上,您是在正确的轨道上-但是您缺少一个要合并数据的源-请尝试以下操作:

MERGE 
   member_topic AS target
USING 
   someOtherTable AS source
ON 
   target.mt_member = source.mt_member 
   AND source.mt_member = 0 
   AND source.mt_topic = 110
WHEN MATCHED THEN 
   UPDATE SET mt_notes = 'test'
WHEN NOT MATCHED THEN 
   INSERT (mt_member, mt_topic, mt_notes) VALUES (0, 110, 'test')
; 
对于单行合并没有特殊的语法-您所需要做的就是使用适当的子句。使用ON子句中的适当条件,可以将源代码限制为一行-没问题

别忘了后面的分号!别开玩笑了,这很重要


请参阅,以获得一个非常好的合并介绍。

我终于在SQL Server 2008中使用MERGE获得了Upsert语法。使用Jacob想要做的一个向上插入:

IF EXISTS(SELECT * FROM member_topic WHERE mt_member = 0 AND mt_topic = 110)
BEGIN
    --update existing row
    UPDATE member_topic SET mt_notes = 'test'
    WHERE mt_member = 0
    AND mt_topic = 110
END
ELSE
BEGIN
    --insert new row
    INSERT INTO member_topic (mt_member, mt_topic, mt_notes)
    VALUES (0, 110, 'test')
END
等效的合并语法为:

MERGE member_topic
USING ( 
    VALUES (0, 110, 'test')
) AS foo (mt_member, mt_topic, mt_notes) 
ON member_topic.mt_member = foo.mt_member 
   AND member_topic.mt_topic = foo.mt_topic
WHEN MATCHED THEN
   UPDATE SET mt_notes = foo.mt_notes
WHEN NOT MATCHED THEN
   INSERT (mt_member, mt_topic, mt_notes)
   VALUES (foo.mt_member, foo.mt_topic, foo.mt_notes)
; --A MERGE statement must be terminated by a semi-colon (;).

嗯,在我的浏览器中,这些行的间距太近,以至于一些下划线没有显示出来。我没有其他表格。你是说我必须用这样的东西来模拟一个?使用选择0 mt_成员,110 mt_主题作为source@Jacob:您必须有一个源,是的-像您提到的子查询应该很好-试试吧!如果有人对这个答案感到困惑,请查看。@NateCook:我的答案令人困惑呢?我想改进它——如果可能的话,这种困惑必须与读者本身对基本原理的误解有关。你的答案没有错。另一个问题只是扩展了主题以进一步澄清。在WHEN NOT MATCHED THEN子句中,为什么要插入值mt_member、mt_topic、mt_notes和NOT VALUES foo.mt_member、foo.mt_topic、foo.mt_notes?@SamP,因为为什么不?是否SQL Server将从伪表foo以外的其他地方获取值?哦,等等……非合并示例中的updatemember_主题SET mt_notes='test'行不会更新表中的所有行吗?我发现IF EXISTS/UPDATE/ELSE/INSERT模式是死锁的来源,在最好的情况下会导致额外的I/O,特别是当EXISTS/UPDATE必须执行扫描时。根据我的经验,一个更好的模式是尝试更新,如果没有行受到影响,则插入。更新/IF@@ROWCOUNT=0/INSERT。是的,我写了第一篇文章。我的观点是,他们都需要保持锁定以避免竞争条件,但你的答案没有保持锁定,而且当你使用UPSERT时,你应该只更新/IF@@ROWCOUNT/INSERT,而不是人们通常在存在/UPDATE/ELSE/INSERT时所做的事。后者出现僵局的可能性更大。