SQL Server MERGE语句的问题

R.D*_*R.D 18 sql t-sql sql-server merge sql-server-2008

来源表

Id, Name, Address
1   A     #202
1   A     #203
1   A     #204
2   A     #202
Run Code Online (Sandbox Code Playgroud)

目标表

Id, Name, Address
1   A     NULL
Run Code Online (Sandbox Code Playgroud)

合并之后

Id, Name, Address
1   A     #202
2   A     #202
Run Code Online (Sandbox Code Playgroud)

我正在使用这个SQL

create table #S   (ID int, Name varchar(25) NULL, Address varchar(25) NULL)
create table #T   (ID int, Name varchar(25) NULL, Address varchar(25) NULL)

 INSERT #S values(1, 'A', '#202')
 INSERT #S values(1, 'A', '#203')
 INSERT #S values(1, 'A', '#203')
 INSERT #S values(1, 'A', '#204')

 INSERT #T values(1, 'A', NULL)

 MERGE #T USING
  (
Select id, name, address 
from #S
  ) AS S(id,name,address)
 on #T.id=S.id and #T.Name=S.Name
 when not matched THEN
    INSERT values(S.id,S.Name, S.Address)
 when matched then
    update set Address = S.Address;
 GO 

 Select * from #T
 GO 

 Select * from #S
 GO 
Run Code Online (Sandbox Code Playgroud)

这会导致错误

消息8672,级别16,状态1,行18
MERGE语句尝试多次更新或删除同一行.当目标行与多个源行匹配时会发生这种情况.MERGE语句不能多次更新/删除目标表的同一行.优化ON子句以确保目标行最多匹配一个源行,或使用GROUP BY子句对源行进行分组.

我想从三个匹配值中的任何一个更新A中带有地址值的行.这该怎么做?

mar*_*c_s 24

四个值中的任何一个#S都将匹配目标表的单行值(#S中的所有值都具有id = 1和name ='A' - 所以它们都匹配目标中的单行),因此该值将更新为四时代 - 这就是错误所说的,这是绝对正确的.

你真的想在这里实现什么?

是否要将地址设置为源表中的第一个值?TOP 1在子选择中使用一个子句:

MERGE #T 
USING (SELECT TOP 1 id, name, address FROM #S) AS S
ON #T.id = S.id AND #T.Name = S.Name
WHEN NOT MATCHED THEN
    INSERT VALUES(S.id,S.Name, S.Address)
WHEN MATCHED THEN
    UPDATE SET Address = S.Address;
Run Code Online (Sandbox Code Playgroud)

是否要将地址设置为源表中值的随机元素?在子选择中使用TOP 1ORDER BY NEWID()子句:

MERGE #T 
USING (SELECT TOP 1 id, name, address FROM #S ORDER BY NEWID()) AS S
ON #T.id = S.id AND #T.Name = S.Name
WHEN NOT MATCHED THEN
    INSERT VALUES(S.id,S.Name, S.Address)
WHEN MATCHED THEN
    UPDATE SET Address = S.Address;
Run Code Online (Sandbox Code Playgroud)

如果将四个源行匹配到单个目标行,则永远不会得到有用的结果 - 您需要知道自己真正想要的是什么.

  • 但是你如何确定使用哪一个? (2认同)
  • 我使用的Row_Number既是源也是目标(视图).然后匹配条件包括附加条件,如果rownumber等于(target.address isnull或(t.address = s.address)) (2认同)