我有一个合并声明
目标表 =~ 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
表结构
Source
Column1 Column2 Column3 Column4
A A NULL NULL
B B NULL NULL
Destination
Column1 Column2 COlumn3 Column4 Column5
错误
MERGE 语句多次尝试更新或删除同一行。当目标行匹配多个源行时会发生这种情况。MERGE 语句不能多次 UPDATE/DELETE 目标表的同一行。优化 ON 子句以确保目标行最多匹配一个源行,或使用 GROUP BY 子句对源行进行分组。
但是当我使用下面的查询时(即只使用那些有一些值而不是空值的列,如 SRC 中的 Column3 和 Column 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].[tblSource](
[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
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
目的地表
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) ;
这工作得非常好,您可以多次运行它。