一对一的关系应该分成两个表吗?

时间:2011-11-08 13:02:37

标签: sql database

我有一个表[Users]和另一个表[Administrators]链接1:0..1。合并这些表是最佳做法吗?我已经阅读了很多关于SO的答案,说明拆分表只是一对多关系所必需的。

我将它们分开的原因是我可以使用AdministratorId而不是一般的UserId来引用管理员。在其他表中,我的字段应该只包含一个管理员,因此它可以作为参考检查。

5 个答案:

答案 0 :(得分:5)

有一条经验法则规定表可以模拟实体/类或实体/类之间的关系,但不能同时模拟两者。但是,这只是一个经验法则,永远不要说永远!

SQL通常存在专用1:1关系表的问题,因为通常发现的唯一的表间约束是外键。但是,FK不要求引用表中存在值。这使得关系1:0..1(“一对零或一”),这通常是可接受的。

严格1:1需要解决方法。由于SQL缺少多个赋值,因此解决方法通常涉及诉诸程序代码,例如两个可延迟的“双向”FK;触发;通过CRUD存储过程强制更新;等

相比之下,在同一个表中建立1:1关系很容易:将两列都声明为NOT NULL

答案 1 :(得分:3)

我认为最好的选择是为两个不同的实体UsersAdministrators设置两个表,可能使用相同的Primary Key

CREATE TABLE User
( UserId int
, ... other data               --- data for all users
, PRIMARY KEY (UserId)
) ;

CREATE TABLE Administrator
( AdministratorId int
, ... other data               --- data for administrators only
, PRIMARY KEY (AdministratorId)
, FOREIGN KEY AdministratorId
    REFERENCES User(UserId)
) ;

这样,正如您所提到的,其他表可以引用AdministratorId

CREATE TABLE OtherTable
( OtherTableId int
, AdministratorId int
, ... other data
, ...
, FOREIGN KEY AdministratorId
    REFERENCES Administrator(AdministratorId)
) ;

优点:

  • 参考完整性很容易实现。
  • 相关数据(针对用户和管理员)可以存储在相关表中,因此表中的列数较少,NULL数据较少。
  • 任何需要JOINAdministrator表的查询都必须只查找几行,而User的行数可能很大表。如果您只有一个表,那么最终会得到如下代码:

    WHERE User.admin = True

    可能不容易优化。

答案 2 :(得分:2)

有几个原因可能会让您将它们分开。一种是如果一个表中的记录代表另一个表中的记录的子集。这种模式称为子分类,在您的情况下显然就是这种情况  即使您需要存储的关于管理员的字段(数据)与您需要存储的关于所有用户的数据没有区别,这也是明智之举。另一个原因是,如果几列的使用模式与其余列的使用模式非常不同(访问频率更高)。

答案 3 :(得分:0)

通常以一对一的关系表格。首先,如果它们是需要单独查询的单独实体,或者它们是子类(如您的情况),则单独的表是有意义的。此外,如果主表对于最大记录大小而言变得太大,则以一对一的关系建立附加表是有意义的。最后你得到的情况是现在关系是1-1,但未来有可能是1-many,例如现在你只有一个电话号码,但可能需要稍后存储更多。在这种情况下,继续进行并使其成为一个单独的表格将会更少。

建立1-1关系的关键是将其强制执行为1-1。最简单的方法是使FK字段也成为第二个表中的PK字段。

答案 4 :(得分:0)

让我首先坚持您的问题的标题。

是的,在需要以下条件时,可以将一对一关系拆分为不同的表:

  1. 模块化
  2. 安全性/数据抽象

我猜模块化程度很清楚。

“安全性”位也很明显,因为您将需要访问两个表以获取整个数据图片。

例如,假设您有以下情况:

Customer and Passport are two different tables. 其中,客户具有护照的虚拟ID,而护照表没有相应的客户信息。 因此,有权访问这两个表的人只能将护照ID与客户对应起来并查看整个图片。

相关问题