Sql server 2008 列中为空时出现Merge语句错误

Sql server 2008 列中为空时出现Merge语句错误,sql-server-2008,join,merge,sql-server-2008-r2,Sql Server 2008,Join,Merge,Sql Server 2008 R2,我有一个合并语句 目标表=~DST 源表=~SRC MERGE DST USING (SELECT * FROM SRC WHERE <Some_Condition>) SRC ON SCR.COL1 = DST.COL1 OR (SRC.COL1 IS NULL AND DST.COl1 IS NULL) AND ON SCR.COL2 = DST.COL2 OR (SRC.COL2 IS NULL AND DST.COl2 IS NULL) AND ON SCR.COL3 =

我有一个合并语句

目标表=~DST 源表=~SRC

MERGE DST
USING (SELECT * FROM SRC WHERE <Some_Condition>) SRC
ON SCR.COL1 = DST.COL1 OR (SRC.COL1 IS NULL AND DST.COl1 IS NULL) AND 
ON SCR.COL2 = DST.COL2 OR (SRC.COL2 IS NULL AND DST.COl2 IS NULL) AND 
ON SCR.COL3 = DST.COL3 OR (SRC.COL3 IS NULL AND DST.COl3 IS NULL) AND 
ON SCR.COL4 = DST.COL4 OR (SRC.COL4 IS NULL AND DST.COl4 IS NULL) 
WHEN MATCHED UPDATE DST
WHEN NOT MATCHED BY SOURCE THEN UPDATE DST
WHEN NOT MATCHED INSERT IN DST
错误

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

但是当我使用下面的查询时(即,只使用那些有一些值的列,而不是空值的列,如SRC中的第3列和第4列)一切正常

MERGE DST
    USING (SELECT * FROM SRC WHERE <Some_Condition>) SRC
    ON SCR.COL1 = DST.COL1 OR (SRC.COL1 IS NULL AND DST.COl1 IS NULL) AND 
    ON SCR.COL2 = DST.COL2 OR (SRC.COL2 IS NULL AND DST.COl2 IS NULL) 
    WHEN MATCHED UPDATE DST
    WHEN NOT MATCHED BY SOURCE THEN UPDATE DST
    WHEN NOT MATCHED INSERT IN DST
目的表

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[tblDestination](
    [Column1] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [Column2] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [Column3] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [Column4] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [Column5] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [Column6] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF
源中的数据

INSERT [dbo].[tblSource] ([Column1], [Column2], [Column3], [Column4], [Column5]) VALUES (N'A', N'A', NULL, NULL, NULL)
INSERT [dbo].[tblSource] ([Column1], [Column2], [Column3], [Column4], [Column5]) VALUES (N'B', N'B', NULL, NULL, NULL)
目的地是空的

合并语句

MERGE dbo.tblDestination DST
USING (SELECT * FROM dbo.tblSource) SRC
ON DST.Column1 = SRC.Column1 OR (DST.Column1 IS NULL AND SRC.Column1 IS NULL) AND
DST.Column2 = SRC.Column2 OR (DST.Column2 IS NULL AND SRC.Column2 IS NULL) AND
DST.Column3 = SRC.Column3 OR (DST.Column3 IS NULL AND SRC.Column3 IS NULL) AND
DST.Column4 = SRC.Column4 OR (DST.Column4 IS NULL AND SRC.Column4 IS NULL) AND
DST.Column5 = SRC.Column5 OR (DST.Column5 IS NULL AND SRC.Column5 IS NULL)

WHEN MATCHED THEN
        UPDATE SET COLUMN5 = 'A'
WHEN NOT MATCHED BY SOURCE THEN
        UPDATE SET Column5 = 'B'
WHEN NOT MATCHED THEN
        INSERT (Column1, Column2, Column3, Column4, Column5)
        VALUES (Column1, Column2, Column3, Column4, Column5) ;
运行两次以查看错误

现在截断目标表

现在使用相同的查询,但只有那些包含数据的列

MERGE dbo.tblDestination DST
USING (SELECT * FROM dbo.tblSource) SRC
ON DST.Column1 = SRC.Column1 OR (DST.Column1 IS NULL AND SRC.Column1 IS NULL) AND
DST.Column2 = SRC.Column2 OR (DST.Column2 IS NULL AND SRC.Column2 IS NULL) 


WHEN MATCHED THEN
        UPDATE SET COLUMN5 = 'A'
WHEN NOT MATCHED BY SOURCE THEN
        UPDATE SET Column5 = 'B'
WHEN NOT MATCHED THEN
        INSERT (Column1, Column2, Column3, Column4, Column5)
        VALUES (Column1, Column2, Column3, Column4, Column5) ;
这是工作绝对好,你可以运行它很多次,你想运行

这是一个问题

DST.Column1=SRC.Column1或(DST.Column1为NULL,SRC.Column1为NULL)…
将匹配所有行,其中
DST.Column1=SRC.Column1
将与其他列中的值无关

您需要在OR:ed条件周围添加一些括号,以覆盖默认优先级

MERGE dbo.tblDestination DST
USING (SELECT * FROM dbo.tblSource) SRC
ON (DST.Column1 = SRC.Column1 OR (DST.Column1 IS NULL AND SRC.Column1 IS NULL)) AND
   (DST.Column2 = SRC.Column2 OR (DST.Column2 IS NULL AND SRC.Column2 IS NULL)) AND
   (DST.Column3 = SRC.Column3 OR (DST.Column3 IS NULL AND SRC.Column3 IS NULL)) AND
   (DST.Column4 = SRC.Column4 OR (DST.Column4 IS NULL AND SRC.Column4 IS NULL)) AND
   (DST.Column5 = SRC.Column5 OR (DST.Column5 IS NULL AND SRC.Column5 IS NULL))

WHEN MATCHED THEN
        UPDATE SET COLUMN5 = 'A'
WHEN NOT MATCHED BY SOURCE THEN
        UPDATE SET Column5 = 'B'
WHEN NOT MATCHED THEN
        INSERT (Column1, Column2, Column3, Column4, Column5)
        VALUES (Column1, Column2, Column3, Column4, Column5) ;

为了更快地得到这个问题的答案,我认为您应该花一些时间添加一些示例代码,以实际显示您遇到的问题。您在此处发布的代码中有很多错误,因此很难找出您真正的问题所在。@Mikael Eriksson我已经用代码和复制场景的步骤更新了我的问题。希望这会有所帮助。您的源示例包含两行完全相同的数据。我猜它们都会在第一次插入,但是如果目标包含匹配的行,它会匹配两个源行,并且您会得到相同的问题。你的真实数据是这样的吗?是否没有一个或多个键列允许您将每个目标行与不超过一个源行进行匹配?是否已解决此问题或仍然存在问题?请使用适当的括号修复Mikael在下面提到的问题。这是唯一的问题。
MERGE dbo.tblDestination DST
USING (SELECT * FROM dbo.tblSource) SRC
ON DST.Column1 = SRC.Column1 OR (DST.Column1 IS NULL AND SRC.Column1 IS NULL) AND
DST.Column2 = SRC.Column2 OR (DST.Column2 IS NULL AND SRC.Column2 IS NULL) 


WHEN MATCHED THEN
        UPDATE SET COLUMN5 = 'A'
WHEN NOT MATCHED BY SOURCE THEN
        UPDATE SET Column5 = 'B'
WHEN NOT MATCHED THEN
        INSERT (Column1, Column2, Column3, Column4, Column5)
        VALUES (Column1, Column2, Column3, Column4, Column5) ;
MERGE dbo.tblDestination DST
USING (SELECT * FROM dbo.tblSource) SRC
ON (DST.Column1 = SRC.Column1 OR (DST.Column1 IS NULL AND SRC.Column1 IS NULL)) AND
   (DST.Column2 = SRC.Column2 OR (DST.Column2 IS NULL AND SRC.Column2 IS NULL)) AND
   (DST.Column3 = SRC.Column3 OR (DST.Column3 IS NULL AND SRC.Column3 IS NULL)) AND
   (DST.Column4 = SRC.Column4 OR (DST.Column4 IS NULL AND SRC.Column4 IS NULL)) AND
   (DST.Column5 = SRC.Column5 OR (DST.Column5 IS NULL AND SRC.Column5 IS NULL))

WHEN MATCHED THEN
        UPDATE SET COLUMN5 = 'A'
WHEN NOT MATCHED BY SOURCE THEN
        UPDATE SET Column5 = 'B'
WHEN NOT MATCHED THEN
        INSERT (Column1, Column2, Column3, Column4, Column5)
        VALUES (Column1, Column2, Column3, Column4, Column5) ;