首页 > 解决方案 > 如何在合并中插入多行?

问题描述

如何在 SQL 的合并中插入多行?我正在使用 MERGE INSERT,我想知道是否可以同时添加两行?下面是我写的查询,但是如您所见,我想为 IsNew 插入两个布尔值,当它不匹配时,我想为 IsNew = 1 和一个 IsNew = 0 添加一行。我该如何实现这个?

MERGE ITEMS AS TARGET
USING @table AS SOURCE
ON T.[ID]=S.ID
WHEN MATCHED THEN
    UPDATE SET 
        T.[Content] = S.[Content],
WHEN NOT MATCHED THEN
    INSERT (ID, Content, TIME, IsNew)
    VALUES (ID, TEXT, GETDATE(), 1),

标签: sql-servertsqlsql-merge

解决方案


您不能直接使用merge语句来执行此操作,但有一个简单的解决方案。

mergestatement<merge_not_matched>子句(即)insert...values|default values子句只能为源表中的每一行在目标表中插入一行。
这意味着要为每个匹配项输入两行,您只需更改源表 - 在这种情况下,它就像交叉连接查询一样简单。

但是,该<merge_matched>子句要求源中只有一行可以匹配目标中的任何一行 - 否则您将收到以下错误:

MERGE 语句多次尝试更新或删除同一行。当目标行匹配多个源行时会发生这种情况。MERGE 语句不能多次 UPDATE/DELETE 目标表的同一行。优化 ON 子句以确保目标行最多匹配一个源行,或使用 GROUP BY 子句对源行进行分组。

要解决此问题,您必须向 中添加一个条件,when match以确保源表中只有一行更新目标表:

MERGE Items AS T
USING (
    SELECT Id, Text, GetDate() As Date, IsNew
    FROM @table
    -- adding one row for each row in source
    CROSS JOIN (SELECT 0 As IsNew UNION SELECT 1) AS isNewMultiplier
       ) AS S
    ON T.[ID]=S.ID
WHEN MATCHED AND S.IsNew = 1 THEN -- Note the added condition here
    UPDATE SET 
        T.[Content] = S.[Text] 
WHEN NOT MATCHED THEN
    INSERT (Id, Content, Time, IsNew) VALUES 
    (Id, Text, Date, IsNew);

您可以在 rextester 上看到现场演示。

说了这么多,我想向您推荐另一个stackoverflow 帖子,它提供了比使用merge语句更好的选择。
答案的作者是 Microsoft MVP 和 SQL Server 专家 DBA,您至少应该阅读他所说的内容。


推荐阅读