Sql 子表中的外键约束允许插入与';t存在于父表中
我正在使用SQL Server 2012。我已经在表上定义了外键约束。外键引用复合主键。当一列具有“00000”而另一列为空时,fk约束不起作用。父表不包含“00000”。两个fk列都具有Sql 子表中的外键约束允许插入与';t存在于父表中,sql,sql-server,sql-server-2012,constraints,Sql,Sql Server,Sql Server 2012,Constraints,我正在使用SQL Server 2012。我已经在表上定义了外键约束。外键引用复合主键。当一列具有“00000”而另一列为空时,fk约束不起作用。父表不包含“00000”。两个fk列都具有varchar数据类型 下面是一个例子: INSERT INTO XYZ ([BUSINESS_PARTNER_ID] ,[INDUSTRY_TYPE_CDE] ,[INDUSTRY_SUBTYPE_CDE]) VALUES (1, Null '00000')
varchar
数据类型
下面是一个例子:
INSERT INTO XYZ
([BUSINESS_PARTNER_ID]
,[INDUSTRY_TYPE_CDE]
,[INDUSTRY_SUBTYPE_CDE])
VALUES
(1,
Null
'00000')
GO
“行业类型”和“行业子类型”列是从另一个表中引用的。
以下是脚本:
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在插入时未给出任何错误。它在子表中插入值。根据我的理解,fk列可以为null,或者应该包含父表中存在的值。虽然您确实应该提供一个完整的示例,如Zohar Peled所说,但您的问题可能在于外键定义中的
WITH NOCHECK
选项。应CHECK
以使外键由发动机启用和强制。事实上,约束是不可信的
有关使用此选项时发生的情况的示例,请参见
当一个或多个列包含null时,为什么不检查fk约束?你能解释一下这种行为吗
首先,我们有实际原因。使用索引维护和检查外键。为了使索引可用,我们需要知道索引中所有列的(查找的)值。如果我们在(a,b)
上有一个索引/pk,并且我们的外键值为(NULL,1)
,那么我们无法在索引中查找以确定是否存在b
值为1的行。这将使外键的维护变得“昂贵”
第二,我们需要考虑一致性。对于单列的情况,这是完全没有争议的-如果FK列中有一个值,那么引用的列中需要有一个匹配的值。否则,如果FK列为NULL
,则不检查约束
但是,我们如何将其扩展到多个列?上面的规则是什么?这里没有一个明显的解释,而是多个解释。上述规则是“如果所有列均为非空,则检查约束”还是“如果任何列均为非空,则检查约束”?当只考虑单个列时,这些规则是相同的
您希望规则是第二条,而事实上它是第一条。这是明确的:
外键约束可以包含空值;但是,如果复合外键约束的任何列包含空值,则将跳过对构成外键约束的所有值的验证。要确保验证复合外键约束的所有值,请在所有参与列上指定NOTNULL
你能写下你的FK并发布它吗?我不知道FK可能在两列上。问题是您不应该被允许输入空值吗?除了Nick提到的以外,请发布错误以及Sql server没有给出任何错误。它在子表中插入值。请编辑您的问题以包括-这意味着样本表DDL、样本数据DML和所需输出。遗憾的是,当一个或多个列为
NULL
时,外键未被选中。您需要将您的设计修改为不使用NULL
s的设计,就像它们是实际值一样。在我的外键脚本中,首先我定义了约束,没有检查。创建约束后,在fk上定义了check约束。@Damien提供了正确答案。我不知道复合外键在null中的行为方式。