Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this a bug in MERGE, failing to implement FOREIGN KEY properly?

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?

like image 463
A-K Avatar asked Oct 14 '11 18:10

A-K


People also ask

How do I fix foreign key constraint failure?

The error message itself showing there is a foreign key constraint error, which means you are deleting a parent table where the child table contains the Primary table identifier as a foreign key. To avoid this error, you need to delete child table records first and after that the parent table record.

What problems do foreign keys introduced?

Foreign key problems. Many database users encounter foreign key errors, often due to referential integrity problems. A foreign key might point to data that no longer exists, or the foreign key's data type doesn't match the primary key data type, eroding referential integrity.

How can avoid foreign key constraint in SQL?

Use SQL Server Management StudioIn Object Explorer, expand the table with the constraint and then expand the Keys folder. Right-click the constraint and select Modify. In the grid under Table Designer, select Enforce Foreign Key Constraint and select No from the drop-down menu. Select Close.

Which one of the following is a disadvantage of adding a foreign key constraint Mcq?

The main disadvantage is the increase in size for the fact table records. You don't specify the sizes of the rows, but adding new foreign keys could significantly impact the size of the row. In most databases, increased row size in the fact table would slow down queries.


1 Answers

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'
like image 161
Martin Smith Avatar answered Nov 15 '22 22:11

Martin Smith