我正在使用 SQL Server 2012。我已经在表上定义了外键约束。外键引用复合主键。当一列具有“00000”而另一列为空时,fk 约束不起作用。父表不包含“00000”。两个 fk 列都有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 时不检查 fk 约束?您能解释一下这种行为吗?
首先,我们有实际的原因。外键是使用索引来维护和检查的。为了使索引可用,我们需要知道索引中所有列的(寻找的)值。如果我们有一个索引/pk(a,b)
我们的外键值为(NULL,1)
, 我们不可以seek索引内以确定是否存在带有b
值为 1。这将使外键的维护“昂贵”。
但其次,我们需要考虑一致性。对于单列情况,这是相当没有争议的 - 如果 FK 列中有一个值,那么引用列中需要有一个匹配的值。否则,如果 FK 列是NULL
那么就不会检查约束。
但是,我们如何将其扩展到多列呢?什么is上面的规则?没有一个single明显的解释,而是多种解释。上述规则是“如果all列非 NULL,则检查约束”或“如果any列非 NULL,则检查约束”?当仅考虑单个列时,这些规则是相同的。
您期望该规则是第二条,而实际上它是第一条。这是明确的记录在案:
FOREIGN KEY 约束可以包含空值;但是,如果复合 FOREIGN KEY 约束的任何列包含空值,则将跳过对构成 FOREIGN KEY 约束的所有值的验证。要确保验证复合 FOREIGN KEY 约束的所有值,请在所有参与列上指定 NOT NULL。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)