I am using the following tables to implement subtypes, which is a very common approach:
CREATE TABLE dbo.Vehicles(
ID INT NOT NULL,
[Type] VARCHAR(5) NOT NULL,
CONSTRAINT Vehicles_PK PRIMARY KEY(ID),
CONSTRAINT Vehicles_UNQ_ID_Type UNIQUE(ID, [Type]),
CONSTRAINT Vehicles_CHK_ValidTypes CHECK([Type] IN ('Car', 'Truck'))
);
GO
CREATE TABLE dbo.Cars(ID INT NOT NULL,
[Type] AS CAST('Car' AS VARCHAR(5)) PERSISTED,
OtherData VARCHAR(10) NULL,
CONSTRAINT Cars_PK PRIMARY KEY(ID),
CONSTRAINT Cars_FK_Vehicles FOREIGN KEY(ID, [Type])
REFERENCES dbo.Vehicles(ID, [Type])
);
GO
-- adding parent rows
INSERT INTO dbo.Vehicles(ID, [Type])
VALUES(1, 'Car'),
(2, 'Truck');
I have no problem adding a child row via INSERT, as follows:
INSERT INTO dbo.Cars(ID, OtherData)
VALUES(1, 'Some Data');
DELETE FROM dbo.Cars;
Surprisingly, MERGE fails to add one child row:
MERGE dbo.Cars AS TargetTable
USING
( SELECT 1 AS ID ,
'Some Data' AS OtherData
) AS SourceData
ON SourceData.ID = TargetTable.ID
WHEN NOT MATCHED
THEN INSERT (ID, OtherData)
VALUES(SourceData.ID, SourceData.OtherData);
Msg 547, Level 16, State 0, Line 1
The MERGE statement conflicted with the FOREIGN KEY constraint "Cars_FK_Vehicles". The conflict occurred in database "Test", table "dbo.Vehicles".
The statement has been terminated.
Is this a bug in MERGE or am I missing something?
Looks like a definite bug in
MERGEto me.The execution plan has the
Clustered Index Mergeoperator and is supposed to output[Cars].ID,[Cars].Typefor validation against theVehiclestable.Experimentation shows that instead of passing the value
"Car"as theTypevalue it is passing an empty string. This can be seen by removing the check constraint on Vehicles then insertingThe following statement now works
But the end result is that it inserts a row violating the FK constraint.
Cars
Vehicles
Checking the constraints immediately afterwards
Shows the offending row