令人惊讶的是,我无法在Google上找到答案,尽管我的术语可能不合适。我也没有看到关于MDSN的解释。
使用以下代码执行简单的MERGE
:
DECLARE @tbl_1 TABLE (ID int IDENTITY(1,1), person nvarchar(20));
DECLARE @tbl_2 TABLE (ID int IDENTITY(1,1), person nvarchar(20));
INSERT INTO @tbl_1 (person) VALUES ('Bob'),('Ted'),('Brian');
INSERT INTO @tbl_2 (person) VALUES ('Bob'),('Ted'),('Peter');
MERGE INTO
@tbl_2 as tgt
USING
@tbl_1 as src
ON
(tgt.person = src.person)
WHEN MATCHED THEN
UPDATE SET tgt.person = src.person
WHEN NOT MATCHED BY TARGET THEN
INSERT (person) VALUES (src.person)
WHEN NOT MATCHED BY SOURCE THEN
DELETE
OUTPUT
$ACTION,
DELETED.ID,
DELETED.person AS PersonOld,
INSERTED.ID,
INSERTED.person AS PersonNew;
在结果中,我看到每行的ID值都针对INSERTED
和DELETED
行显示,其中UPDATE
已经发生:
为什么这样好?我希望更新后DELETED.ID
为NULL
,INSERTED.ID
代表 UPSERTED 行(我过去曾使用过触发器,并假设{{ 1}}将遵循相同的方法。)
答案 0 :(得分:3)
因为您似乎知道MERGE
是UPSERT
(更新+插入)。
现在,INSERTED
表记录了由INSERT
&添加的行添加的行的信息。 UPDATE
个命令和DELETED
表包含已更新或删除的行的信息。
看看MSDN documentation on how to "Use the inserted and deleted Tables":
插入表在INSERT期间存储受影响行的副本 和UPDATE语句。在插入或更新事务期间,新的 行被添加到插入的表和触发器表中。该 inserted表中的行是触发器中新行的副本 表
和
更新事务类似于删除操作后跟一个 插入操作;先将旧行复制到已删除的表中, 然后将新行复制到触发器表和 插表。
<强>更新强>
我看到你评论了你的问题,你发现这个操作实际上是一个 delsert 。你可能会想到为什么会这样?
考虑如何在SQL Server中存储数据。它存储在8KB页面上,当您更新数据页面中包含的列中的信息时,整个数据页面将被重写,因此基本上是 delsert 。
与INSERT
相同的是,新行将进入数据页面(并且可能会生成页面拆分 - 但这是另一个主题)并且必须重写整个数据页面。