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

jam*_*ams 287 sql sql-server oracle foreign-keys

请为我澄清两件事:

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

据我所知,NULL不应该在外键中使用,但在我的某些应用程序中,我能够NULL在Oracle和SQL Server中输入,我不知道为什么.

HLG*_*GEM 474

简答:是的,它可以是NULL或重复.

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

让我给你一个真实的例子.假设您有一个存储销售提案的数据库.进一步假设每个提案仅分配了一个销售人员和一个客户.因此,您的提议表将有两个外键,一个具有客户端ID,另一个具有销售代表ID.但是,在创建记录时,并不总是分配销售代表(因为没有人可以自由处理它),因此填写了客户端ID,但销售代表ID可能为空.换句话说,当您在输入数据时可能不知道其值时,通常需要具有空FK的能力,但您确实知道表中需要输入的其他值.要允许FK中的空值,通常您只需要在具有FK的字段上允许空值.null值与它是FK的想法是分开的.

它是唯一的还是不唯一的,与表是否与父表具有一对一或一对多的关系有关.现在,如果你有一对一的关系,你有可能将数据全部放在一个表中,但如果表格太宽或者数据是在另一个主题上(员工 - 保险示例@tbone给出了)例如),那么你想要一个带有FK的单独表.然后你想要使这个FK也是PK(它保证唯一性)或对它施加一个独特的约束.

大多数FK用于一对多的关系,这是你从FK获得的,而不在场上添加进一步的约束.所以你有一个订单表和订单详情表.如果客户一次订购十件商品,他有一个订单和十个订单明细记录,其中包含与FK相同的订单ID.

  • @ThomasWeller引用假销售员("未分配")会使问题变得更糟.我假设您的销售人员表有多列...?Mr. Unassigned的社会保险号码是什么?他被分配到哪个部门?谁是他的老板?我希望你明白我的观点:当你创建一个"未分配"的销售人员时,你会很快发现你在一个表中交换了`NULL`,在另一个表中有多个`NULL`. (24认同)
  • @nWest,我不允许不称职的人查询我的数据库,任何不知道如何处理空值的开发人员都不称职.有时在特定字段的初始数据输入时不知道数据,但此时需要其他字段. (21认同)
  • 这样做的目的是为了比一个名为"未分配"的假销售人员更好? (12认同)
  • 一条评论.对于不知道SQL(错误)如何处理3VL的人来说,Nulls在查询中留下了很大的错误空间.如果某个r-table真的不需要销售人员,那么就不包括该记录.一个单独的表可以是"ProposalAssignedTo"或其他一些具有适当约束的表.然后,查询编写者可以加入该表,并在提案没有销售人员时为我们想要做的事情提供他们自己的逻辑.NULL不只是意味着"我们不知道" - 它可以用于很多事情(这就是为什么它几乎总是一个坏主意) (6认同)

JNK*_*JNK 48

1 - 是的,至少从SQL Server 2000开始.

2 - 是的,只要它不是UNIQUE约束或链接到唯一索引.

  • 该链接已失效。 (2认同)

tbo*_*one 44

从马的嘴里:

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

对外键没有限制

如果未在外键上定义其他约束,则子表中的任何行数都可以引用相同的父键值.此模型允许外键中的空值....

外键上的NOT NULL约束

如果外键中不允许空值,则子表中的每一行都必须显式引用父键中的值,因为外键中不允许使用空值.

子表中的任意数量的行都可以引用相同的父键值,因此该模型在父键和外键之间建立一对多关系.但是,子表中的每一行都必须引用父键值; 不允许在外键中缺少值(null).可以使用上一节中的相同示例来说明这种关系.但是,在这种情况下,员工必须具有对特定部门的引用.

对外键的唯一约束

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

此模型在父键和外键之间建立一对一关系,允许外键中的未确定值(空值).例如,假设employee表有一个名为MEMBERNO的列,指的是公司保险计划中的员工成员编号.此外,名为INSURANCE的表具有名为MEMBERNO的主键,该表的其他列保留与员工保险单相关的相应信息.employee表中的MEMBERNO必须是外键和唯一键:

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

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

外键上的UNIQUE和NOT NULL约束

如果在外键上定义了UNIQUE和NOT NULL约束,则子表中只有一行可以引用给定的父键值,并且因为外键中不允许使用NULL值,所以子表中的每一行都必须显式引用父键中的值.

看到这个:

Oracle 11g链接


小智 16

是的,外键可以为null,如上面高级程序员所说...我会添加另一个场景,其中外键需要为null ....假设我们在应用程序中有表评论,图片和视频,允许对图片和视频.在注释表中,我们可以有两个外键PicturesId,以及VideosId和主键CommentId.因此,当您对视频发表评论时,只需要VideosId并且pictureId将为null ...如果您对图片发表评论,则只需要PictureId,而且VideosId将为null ...

  • @Agent:我们在生产使用中有这个"解决方案".不要这样做,这太可怕了.使查询变得混乱,"如果它是类型1,则加入此表,否则加入此".这对我们来说是一场噩梦.我们最终做了这个答案所说的内容,并为每种类型的连接创建了一个新列.创建列很便宜.几乎唯一的缺陷就是很多柱子让Toad难以使用,但这只是Toad的一个缺陷. (2认同)
  • @Agent:也许它可以......但如果你可以让它变得简单,为什么要让它变得复杂?也许“噩梦”这个词用错了:它只是非常不方便。我们没有受到数据完整性问题的困扰(很多)。 (2认同)

shi*_*nxg 6

这取决于它foreign key在你的关系中起什么作用.

  1. 如果这foreign key也是key attribute你的关系,那么它不能是NULL
  2. 如果这foreign key是您关系中的普通属性,则它可以为NULL.

  • “关键属性”是什么意思? (15认同)