数据库:将外键置于“有”关系的位置?

时间:2012-04-03 14:15:12

标签: sql database postgresql foreign-keys ddl

我有一个包含两种用户的数据库。类似的东西:

User:
    name: String
    email: String

PowerUser
    address: String
    paypalAcct: String

每个用户都是User,但注册了扩展服务等的用户也会在其帐户中附加PowerUser。我想将UserPowerUser分开,因为我认为对已经成为User的人重复使用PowerUser表会很好,因为他们应该有所有正常的东西User都有。

这是正确的做法,还是应该将User字段添加到PowerUser表中并使用它?

如果这是正确的做法,User应该有一个指向PowerUser的外键,或者PowerUser是否有一个指向{{1}的外键}?我猜这取决于这些东西应该访问的顺序?在这种情况下,我几乎总是从User开始检查是否存在相关的User,而不是反过来。

如果我将外键放在PowerUser中,那么大量用户将拥有一个空外键。如果我将外键放在User中,那么它们都将被填充,但从PowerUsersUser s将需要遍历整个PowerUser表。哪个更好?

3 个答案:

答案 0 :(得分:2)

显而易见的答案是将外键添加到从属表中。用户不需要 PowerUser信息。

  

如果我把外键放在PowerUsers中,那么它们都会被填满,但是从用户到PowerUsers需要迭代整个PowerUsers表。

您不需要迭代。您可以使用left outer join syntax

获取包含其超级用户信息的所有用户的列表(如果他们有用户信息)
select 
    a.id, a.email, a.name, a.email, b.address, b.paypalacct 
from 
    users a 
    left outer join powerusers b on a.id = b.id

如果您只想获得超级用户列表,请使用inner join

select
    a.id, a.email, a.name, a.email, b.address, b.paypalacct
from 
    users a 
    inner join powerusers b on a.id = b.id

答案 1 :(得分:1)

你快要回答自己了:

如果使用单个表,则会有很多空值。空值不好,特别是用于索引。所以你最好使用一个单独的表。

至于FK,如果你在PowerUser中添加FK,你将拥有一个非空列,它可以是第二个表中的主键。因此,为用户查找PowerUser条目非常快。

答案 2 :(得分:1)

易于索引的代理键是可取的(通常与用户帐户数据一样):

User:
    id            INTEGER NOT NULL PRIMARY KEY
    name          VARCHAR
    email         VARCHAR

PowerUser:
    id            INTEGER NOT NULL PRIMARY KEY REFERENCES(User.id)
    ...

从技术上讲,您也可以使用用户名,但这会在更改用户名时引起重大麻烦,并且迟早会出现在几乎所有用户数据库中。 PRIMARY KEY索引使查找速度足够快,因此没有真正的性能损失。