是否可以在规范化的数据库模式中拥有多个外键?

时间:2018-02-22 12:40:35

标签: database foreign-keys relational-database database-normalization

  

地址(地址ID ,houseNumber,邮政编码,道路名称,城市,县)
  预订( reservationID ,roomNo, leadGuestID,guest2ID,guest3ID
  arrivalDate,departureDate, addressID ,amountOutstanding)
  访客(访客ID ,firstName,lastName,adultFlag,telephoneNo, addressID ,emailAddress)
  房间( roomNo roomTypeName
  RoomType( roomTypeName ,floor,basePrice,extraAdultPrice,extraChildPrice)

上述模式应该归一化为4NF。但我看不出 leadGuestID,guest2ID& guest3ID 可以是外键,因为它们不作为任何其他表中的主键存在。这里可能还有其他问题。

2 个答案:

答案 0 :(得分:0)

外键不必引用主键(它们可以引用任何唯一键,在某些DBMS中可以引用任何索引列)并且不必具有与引用列相同的名称。

列名称是两个逻辑概念(域和角色)的不良替代品。域是指列中有效的值集。角色指的是列的含义或目的。例如,在(manager, subordinate)关系中,两列的域都是有效员工标识符的集合,而角色则指示谁向谁报告。通常,当关系中只出现一个域时,不需要指明该角色。

规范化的目的是消除产生不一致数据风险的冗余功能和连接依赖性。在确定模式中当前的正常形式或问题之前,确定并列出功能和连接依赖关系是必要的。它不能从列名完成。了解数据模型的业务领域可能使建模者能够快速查看可能的违规行为,但即使有经验的建模人员如果不列出依赖关系也会犯错误,因此如果您关注模式,请从那里开始。

即使是最高级的正常形式,也可能在关系中拥有多个外键。 SQL中的外键约束只是强制域完整性的一种方式,它们不会以任何方式影响依赖关系和/或规范化。

请注意,我并不是说leadGuestID, guest2ID, guest3ID是好的设计。客人和预订之间的关系应该记录在一个单独的表格中,但这样的设计不会违反前4种正常形式。

答案 1 :(得分:0)

FK(外键)约束的概念略有不同& FK也被使用。一种是,当引用列表的第n个属性/列下的值必须出现在下面时,引用另一个关系/表中的列表的一个关系/表(值或基数或表达式)中的属性/列列表中存在FK约束。引用列表的第n个属性/列&引用列表的属性/列集是超级键。 (引用和引用的属性/列列表不必相同。与NF(正常形式)关系/表格的关系并不重要。)

我们将引用列表称为FK。这种约束也被称为FK。我们声明了足够的FK约束,这样当我们声明的那些约束时,其他人也必须持有。

要确定约束(超级密钥,CK,FK等),我们需要知道在给定情况下哪些行应该进入每个基础(否则我们无法理解或更新数据库)以及可能的值是什么根据可能出现的情况限制持有。

  

预订(reservationID,roomNo, leadGuestID guest2ID guest3ID ,[...])
  访客(访客ID ,[...])

大概是每个leadGuestID,guest2ID&预订中的guest3ID必须显示为Guest guestID下的值,您显示的是Guest的CK。如果是这样,则以下FK约束成立:

Reservation (leadGuestID) references Guest (guestID)
Reservation (guest2ID) references Guest (guestID)
Reservation (guest3ID) references Guest (guestID)

Re FKs正常化:

当归一化到更高的NF时,我们用它的多个投影替换基本关系/表。所以原来的&组件在每个属性/列下都具有相同的值集。因此,对于每个组件的每个超级键,具有这些属性/列的每个组件(本身或其他组件)必须在它们下面具有相同的子组/子组。因此,后一个组件到那些属性/列上的前一个组件有一个FK约束。

类似地,如果存在从原始到某个基础的FK约束,则具有其引用属性/列的每个组件对该基础具有FK约束。类似地,如果存在从某个基础到原始的FK,则对于具有原始超级密钥的每个组件,存在来自基础的FK约束。即使组件在具有基础的FK约束中仅具有其原始引用或引用列表的某些属性/列,该组件可能具有FK约束,该基础涉及该先前FK约束的子列表。

当您用组件替换基础时,您将丢失涉及基础的FK,因此除了根据上面的新FK添加声明之外,您可能还必须为丢失的FK隐含的每个FK添加其他声明。

PS P PK(主键)是你决定调用PK的CK。 PK对于FK或正常化并不重要。