同一两张桌子上有多对一和一对一的关系?

时间:2011-07-13 16:05:33

标签: mysql database-design data-modeling

我正在设计一个数据库,其中两个字段具有多对一关系,但我也需要它们之间的一对一关系,我想就是否有更好的方法做一些建议它比我现在所拥有的还要多。

我的表格为accountsusers。一个帐户可以有多个用户,但每个帐户只能且必须拥有一个所有者。用户只能与一个帐户相关联。

我在account表中有一个users字段,用于存储用户所关联帐户的ID。在accounts表中,我有一个owner字段,用于存储拥有该帐户的用户的ID(即主管理员)。

我正在使用InnoDB,所以我可以使用外键。问题是我不能创建一个帐户或用户没有先创建另一个(由于外键的限制),所以我使owner可以为空。现在我可以使用空owner创建一个帐户,然后创建用户,最后将该帐户的owner设置为该用户。

这是否可以接受,是否有更好的方法?

以下是我提出的一些可能的其他方式,以及我对每个方面的看法:

  1. owner表格中有一个布尔users字段。由于每个帐户只能拥有一个所有者,因此这种方式似乎不太理想,因为我必须确保每个帐户只有一个用户将该属性设置为true

  2. 有第三个名为owners的表格。这似乎是更多的开销和更多的工作,没有充分的理由,因为它实际上与owner表中的users字段相同。

  3. 我现在如何对我有意义,但是在我创建用户之前设置一个null所有者,然后在事后再回来设置它有点尴尬。

    我很感激你能给我的任何意见。谢谢!

    这个问题很相似,但没有提到外键:Designing Tables: One to many and one to one at same time?

3 个答案:

答案 0 :(得分:4)

一般来说,如果你的模式不能在拓扑上进行排序,那就是一个坏主意,即如果你不能建立一个表,其中一个表只引用排序中前面的表。这种“分层”依赖关系也是一个非常好的属性,例如对于软件模块(如果两个模块相互依赖,则会出现问题)。

在您的情况下,您的用户会引用引用用户的帐户和帐户,因此无法找到拓扑排序。

在这种情况下,一个标准解决方案是引入一个单独的表,例如“角色”,其中有三列:用户,帐户和角色。列角色可以是“所有者”或“访客”。

您知道(根据当前请求)帐户必须拥有一个且只有一个所有者,或者用户必须在一个且仅一个帐户中列出的事实不是与该域名真正相关的IMO规则“用户”和“帐户”。

您可以轻松实施这些规则,但构建数据以便您没有其他可能性是IMO的错误。你的目标应该是建立域名,而不是具体的规则......因为人们会改变他们对这些规则的看法。

你能怀有有两个帐户的用户吗?你能构思一个拥有多个所有者/管理员的帐户吗?我可以......这意味着很可能很快这将是一个请求。构建数据以便您无法代表这一点正在寻找麻烦。

此外,当您在模型中具有循环依赖性时,您的查询将更难编写。

一个非常常见的情况是,例如尝试使用一个带有“父”字段的表来表示分层部件列表数据库,该字段指向表本身... 很多更好的是有两个表而是部件和组件,其中组件具有对零件和数量的两个引用。

答案 1 :(得分:1)

你的解决方案很好。

如果你对所有者列可以为空可能感到不舒服,你可以依赖一些魔术用户记录(可能是id为零),这将是“系统用户”。因此,新创建的帐户将由用户零拥有,直到他们的所有权被适当地重新定义。无论如何,这似乎比允许帐户拥有一个空所有者更有气味。

答案 2 :(得分:0)

enter image description here

目前要求每个用户只有一个帐户

alter table UserAccount add constraint un_user_account unique(UserID);

当需求变为多对多时,删除约束

alter table UserAccount drop constraint un_user_account;

仅限一位所有者,只需在应用程序级别强制执行该操作。