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 MAT开发者_高级运维CHED
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 MERGE
to me.
The execution plan has the Clustered Index Merge
operator and is supposed to output [Cars].ID,[Cars].Type
for validation against the Vehicles
table.
Experimentation shows that instead of passing the value "Car"
as the Type
value it is passing an empty string. This can be seen by removing the check constraint on Vehicles then inserting
INSERT INTO dbo.Vehicles(ID, [Type]) VALUES (3, '');
The following statement now works
MERGE dbo.Cars AS TargetTable
USING
( SELECT 3 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);
But the end result is that it inserts a row violating the FK constraint.
Cars
ID Type OtherData
----------- ----- ----------
3 Car Some Data
Vehicles
ID Type
----------- -----
1 Car
2 Truck
3
Checking the constraints immediately afterwards
DBCC CHECKCONSTRAINTS ('dbo.Cars')
Shows the offending row
Table Constraint Where
------------- ------------------- ------------------------------
[dbo].[Cars] [Cars_FK_Vehicles] [ID] = '3' AND [Type] = 'Car'
精彩评论