Foreign Key Constraint in child table allows to insert values that doesn't exists in the parent table

房东的猫 提交于 2020-03-15 05:49:17

问题


I am using SQL Server 2012. I have defined a foreign key constraint on a table. The foreign key references composite primary key. The fk constraint does not work when one column has '00000' and other column is null. The parent table does not contain '00000'. Both of the fk columns have varchar data type.

Below is the example:

INSERT INTO XYZ
    ([BUSINESS_PARTNER_ID]
    ,[INDUSTRY_TYPE_CDE]
    ,[INDUSTRY_SUBTYPE_CDE])
VALUES
    (1,
    Null
    '00000')
GO

The industry type and industry sub type column is referenced from another table. Below is the script:

ALTER TABLE [nfs].[xyz] WITH NOCHECK 
ADD CONSTRAINT [FK_BPMAIN__ITCDE_ISTCDE] 
FOREIGN KEY([INDUSTRY_TYPE_CDE], [INDUSTRY_SUBTYPE_CDE]) 
REFERENCES [nfs].[abc] ([INDUSTRY_TYPE_CDE], [INDUSTRY_SUBTYPE_CDE]) 
GO 

ALTER TABLE [nfs].[xyz] 
CHECK CONSTRAINT [FK_BPMAIN__ITCDE_ISTCDE] 
GO 

SQL Server does not give any error on insertion. It inserts the value in the child table. According to my understanding, the fk columns can be null or should contain values that exist in the parent table.


回答1:


why does the fk constraint isn't checked when one or more column contains null? Can you please explain this behavior?

First, we have the practical reasons. Foreign keys are maintained and checked using indexes. In order for an index to be usable, we need to know the (sought for) values of all columns within the index. If we have an index/pk on (a,b) and we have a foreign key value of (NULL,1), we cannot seek within the index in order to determine whether there is any row with a b value of 1. This would make the foreign key "expensive" to maintain.

But secondly, we need to consider consistency. For the single column case, its fairly uncontroversial - if you have a value in the FK column, then there needs to be a matching value in the referenced column. Otherwise, if the FK column is NULL then the constraint isn't checked.

But, how do we extend this to multiple columns? What is the rule above? There's not a single obvious interpretation, but instead multiple ones. Is the above rule "if all columns are non-NULL, then the constraint is checked" or "if any columns are non-NULL, then the constraint is checked"? These rules are identical when only a single column is under consideration.

You expected the rule to be the second one, when it is in fact the first. This is explicitly documented:

A FOREIGN KEY constraint can contain null values; however, if any column of a composite FOREIGN KEY constraint contains null values, verification of all values that make up the FOREIGN KEY constraint is skipped. To make sure that all values of a composite FOREIGN KEY constraint are verified, specify NOT NULL on all the participating columns.




回答2:


While you really should have provided a complete example as Zohar Peled said, it is likely that your problem lies in the WITH NOCHECK option in the foreign key definition. It should be CHECK to make the foreign key enabled and enforced by the engine. The way it is, the constraint is not trusted.

See What is lost when I create a Foreign Key using WITH NOCHECK for examples what happens when you use this option.



来源:https://stackoverflow.com/questions/38045684/foreign-key-constraint-in-child-table-allows-to-insert-values-that-doesnt-exist

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!