T-SQL中的合并语句出错

时间:2016-02-27 12:38:53

标签: sql-server

我有我的存储过程:

create procedure [dbo].[Sp_AddPermission]
@id nvarchar(max)
as
    declare @words varchar(max), @sql nvarchar(max)
    set @words = @id

    set @sql = 'merge admin AS target
    using (values (''' + replace(replace(@words,';','),('''),'-',''',') + ')) AS source(uname, [add], [edit], [delete], [view],Block)
on target.uname = source.uname
when matched then update set [add] = source.[add], [edit] = source.[edit], [delete] = source.[delete], [view] = source.[view], [Block]=source.[Block];'

    exec(@sql);

执行时,会显示以下错误:

  

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

如何解决这个问题?

此致

白菊

1 个答案:

答案 0 :(得分:2)

问题很明显:您为同一uname生成了一个包含多个值的源表。

为什么要使用merge?我认为只需进行简单的更新,当update中有多个相同的密钥时,我认为source不会返回错误:

update t
    set [add] = source.[add],
        [edit] = source.[edit],
        [delete] = source.[delete],
        [view] = source.[view],
        [Block]=source.[Block]
    from target t join
         (values(. . . )) s(uname, [add], [edit], [delete], [view],Block)
         on t.uname = s.uname;

但是,你可以通过为更新选择一个任意行来解决这个问题(这就是上面所做的):

update t
    set [add] = source.[add],
        [edit] = source.[edit],
        [delete] = source.[delete],
        [view] = source.[view],
        [Block]=source.[Block]
    from target t join
         (select s.*,
                 row_number() over (partition by uname order by uname) as seqnum
          from (values(. . . )) s(uname, [add], [edit], [delete], [view],Block)
         ) s
         on t.uname = s.uname and s.seqnum = 1;

当然,这种方法也可以与merge一起使用。