マージステートメントがあります
DESTINMATION TABLE =〜DST SOURCE TABLE =〜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ステートメントは、同じ行を複数回UPDATEまたはDELETEしようとしました。これは、ターゲット行が複数のソース行と一致する場合に発生します。MERGEステートメントは、ターゲットテーブルの同じ行を複数回更新/削除することはできません。ON句を調整して、ターゲット行が最大で1つのソース行と一致するようにするか、GROUPBY句を使用してソース行をグループ化します。
しかし、以下のクエリを使用している場合(つまり、SRCのColumn3やColumn 4のように、いくつかの値があり、null値ではない列のみを使用している場合)すべてが正常に機能します
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) ;
エラーを確認するには、2回実行します。
次に、宛先テーブルを切り捨てます
これで同じクエリになりますが、データを持つ列のみが含まれます
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) ;
これは非常にうまく機能しており、実行したい回数だけ実行できます。