FK / PK和FK null问题

时间:2010-12-18 10:52:29

标签: database schema

我正在为我的用户内容网站设计一些表格,在这种情况下我迷失在FK概念上。这两种情况有什么不同:

案例A:
朋友表
user_id(FK)
friend_id(FK)

案例B:
朋友表
id(PK)
user_id(FK)
friend_id(FK)

我想要了解的是,一张桌子有2个FK,1张有2个FKS + 1 PK。我见过的大多数架构给朋友的案例A只有2个FK且没有PK。但我看到的大多数其他表都有PK的案例B.那么这两个表的差异/优势/劣势是什么?使用哪一个?


我遇到的第二个问题是,如果我在表A中有一个PK并在表B中将其用作FK,它是否必须在表B中为NOT NULL,或者它可以为NULL,即使在表A中是PK也是必须是非NULL?一个例子是映射城市和州。状态表中的状态必须为NOT NULL。在城市表中我将所有值存储为NOT NULL DEFAULT 0,因为没有城市有状态(世界城市),但我不想在db中存储NULL,所以我为所有空值写0只是为了保持单元格占用。

3 个答案:

答案 0 :(得分:1)

在案例A中,虽然user_id和friend_id是FK,但它们都很可能是复合主键。在案例B中,有一个单独的PK(id)来识别每个独特的友谊。它们实际上都做同样的事情,但根据我的观点,第二种情况下的 id 是多余的,因为PK(user_id,friend_id)可以一起行动成为一个复合主键,它将唯一地识别每个友谊。我建议你读一本关于规范化的好书:)

答案 1 :(得分:1)

根据给出的信息,A和B之间的区别在于B有一个额外的列和键约束。哪种设计有意义取决于要求以及数据对您的意义。

可能是在A中,主键实际上是复合键:(user_id,friend_id)。在这种情况下,两种选择之间的区别在于A不允许用户和朋友的重复组合,而B确实允许这些重复。这是一个显着的差异。

最好避免使用可以为空的外键。如果您有一个并不总是适用的属性,那么您可以随时重新设计表,这样您就不需要具有可为空的列。如果城市没有州,则将州置于另一个不需要填充的表中。

答案 2 :(得分:0)

建议使用案例A.

当您需要将长复合键迁移到另一个表时,通常会使用案例B.例如,假设我们需要在表T1和T2之间创建多对多关系(T3)。

Case A (natural keys):
table T1(pk1, pk2, pk3, pk4, someValue)
table T2(pka, pkb, pkc, pkd, otherValue)
table T3(pk1, pk2, pk3, pk4, pka, pkb, pkc, pkd, create_date)

需要三个唯一索引(每个表中一个)。很容易直接查询T3。

Case B (surrogate keys):
table T1(t1_id, pk1, pk2, pk3, pk4, someValue)
table T2(t2_id, pka, pkb, pkc, pkd, otherValue)
table T3(t1_id, t2_id, create_date)

需要五个独特的索引。与案例A相同的三个,每个代理键加一个。 T3现在变得更小,但代价是不再能够在不加入T1或T2的情况下查询M:M关系。对于任何典型应用,这可能是也可能不是很重要。

我认为这几乎总结了它。