外键可以是NULL和/或重复吗?

请为我澄清两件事情:

  1. 外键可以是NULL吗?
  2. 外键可以重复吗?

就我所知, NULL不应该用在外键上,但在我的一些应用程序中,我可以在Oracle和SQL Server中inputNULL ,我不知道为什么。

简短的回答:是的,它可以是NULL或重复。

我想解释为什么外键可能需要为空或可能需要是唯一的或不唯一的。 首先记住一个外键只需要该字段中的值必须首先存在于不同的表(父表)中。 根据定义,这就是所有的FK。 根据定义,空值不是一个值。 空意味着我们还不知道什么是价值。

让我给你一个真实的例子。 假设您有一个存储销售build议的数据库。 进一步假设每个提案只有一个销售人员和一个客户。 所以你的build议表将有两个外键,一个是客户端ID,另一个是销售代表ID。 但是,在创buildlogging时,销售代表并不总是被分配(因为没有人可以自由处理),所以客户ID被填写,但销售代表ID可能为空。 换句话说,通常你需要能够在input数据时不知道它的值的情况下有一个空的FK,但是你知道表中需要input的其他值。 为了允许FK中的空值,通常所有你需要做的就是允许有FK的字段上的空值。 空值与作为FK的想法是分开的。

无论是唯一的还是不唯一的,关系到表是与父表有一对一还是一对多的关系。 现在,如果你有一对一的关系,你可能会把所有的数据全部放在一张表中,但是如果表格变得太宽泛,或者数据是在不同的话题上(@tbone雇员保险示例给出的例如),那么你想要与FK分开的表。 然后你会想要使这个FK或者PK(保证唯一性)或者给它一个唯一的约束。

大多数FK是一对多的关系,这就是你从FK得到的,而不是在这个领域增加进一步的限制。 所以你有一个订单表和订单详细信息表。 如果客户一次订购10件商品,则他有一个订单和十个订单明细logging,其中包含与FK相同的订单ID。

1 – 是的,因为至lessSQL Server 2000。

2 – 是的,只要它不是一个UNIQUE约束或链接到一个唯一的索引。

从马的口中:

即使没有匹配的PRIMARY或UNIQUE键,外键也允许全部为NULL的键值

对外键没有限制

当外键上没有定义其他约束时,子表中的任意数量的行都可以引用相同的父键值。 这个模型允许在外键中使用空值。 …

外键的NOT NULL约束

在外键中不允许使用空值时,子表中的每一行都必须显式引用父键中的值,因为外键中不允许有空值。

子表中的任意数量的行都可以引用相同的父键值,所以这个模型build立了父键和外键之间的一对多关系。 但是,子表中的每一行都必须具有对父键值的引用; 外键中不存在值(空)是不允许的。 上一节中的相同示例可以用来说明这种关系。 但是,在这种情况下,员工必须参考特定的部门。

外键上的唯一约束

当在外键上定义一个UNIQUE约束时,子表中只有一行可以引用给定的父键值。 这个模型允许在外键中使用空值。

这个模型在父键和外键之间build立了一个一对一的关系,允许外键中的未定值(空值)。 例如,假设员工表有一个名为MEMBERNO的列,指的是公司保险计划中的员工会员编号。 此外,一个名为INSURANCE的表有一个名为MEMBERNO的主键,表中的其他各列保存了有关雇员保险单的相关信息。 employee表中的MEMBERNO必须是外键和唯一键:

  • 为了在EMP_TAB和INSURANCE表(FOREIGN KEY约束)之间执行参照完整性规则,

  • 为了保证每个员工都有唯一的会员号码(UNIQUE键约束)

外键的唯一和非NULL约束

当在外键上定义了UNIQUE和NOT NULL约束时,子表中只有一行可以引用给定的父键值,并且由于NULL值不允许在外键中,所以子表中的每一行都必须显式引用父键中的一个值。

看到这个:

Oracle 11g链接

是的,外键可以是空的,正如高级程序员所说的那样…我会添加另一个场景,其中外键将被要求为空….假设我们在应用程序中有表格评论,图片和video,允许评论图片和video。 在评论表中,我们可以有两个外键PicturesId和VideosId以及主键CommentId。 所以,当你评论一个video时,只有VideosId是必需的,而pictureId将是空的…如果你对一张图片发表评论,只有PictureId将是必需的,而VideosId将为空…

以下是使用Oracle语法的示例:
首先让我们创build一个表COUNTRY

 CREATE TABLE TBL_COUNTRY ( COUNTRY_ID VARCHAR2 (50) NOT NULL ) ; ALTER TABLE TBL_COUNTRY ADD CONSTRAINT COUNTRY_PK PRIMARY KEY ( COUNTRY_ID ) ; 

创build表格省

 CREATE TABLE TBL_PROVINCE( PROVINCE_ID VARCHAR2 (50) NOT NULL , COUNTRY_ID VARCHAR2 (50) ); ALTER TABLE TBL_PROVINCE ADD CONSTRAINT PROVINCE_PK PRIMARY KEY ( PROVINCE_ID ) ; ALTER TABLE TBL_PROVINCE ADD CONSTRAINT PROVINCE_COUNTRY_FK FOREIGN KEY ( COUNTRY_ID ) REFERENCES TBL_COUNTRY ( COUNTRY_ID ) ; 

这在Oracle中运行得非常好。 注意第二个表中的COUNTRY_ID外键没有“NOT NULL”。

现在要在PROVINCE表中插入一行,只需指定PROVINCE_ID即可。 但是,如果您也select指定COUNTRY_ID,则它必须已经存在于COUNTRY表中。

简而言之,实体之间的“非识别”关系是ER-Model的一部分,在deviseER-Diagram时可在Microsoft Visio中find。 这是在“零或大于零”或“零或一”types的实体之间强制实施基数所必需的。 注意基数中的“零”而不是“一对多”中的“一”。

现在,基数可以是“零”(非识别)的非识别关系的例子是当我们在一个实体中说出一个logging/对象 – “可能”或“不可以”具有作为对logging的引用的值/ s在另一个实体-B中。

因为实体-A的一条logging有可能将自己标识给其他实体-B的logging,所以在实体-B中应该有一列具有实体-B的logging的标识值。 如果Entity-A中没有logging标识Entity-B中的logging(或者对象),则该列可以是“Null”。

在面向对象(现实世界)范式中,存在这样的情况,即类别B的对象不一定依赖(强烈耦合)类别A的对象来存在,这意味着类别B与类别对象A类可以“包含”(包含)一个类A的对象,而不是类B的对象的概念必须具有(构成)类A的对象,因为它的类(对象类) B)创作。

从SQL查询的angular度来看,您可以查询实体-B中所有为“实体-B”保留的外键“非空”的logging。 这将为实体-A中的行带来具有特定对应值的所有logging,或者,具有空值的所有logging将是在实体-B中的实体-A中没有任何logging的logging。

我认为一个表的外键也是其他表的主键,所以它不会允许null。所以在外键中没有空值的问题。