【问题标题】:Many-to-One and One-to-One Relationships on Same Two Tables?同一两张表上的多对一和一对一关系?
【发布时间】:2011-10-04 15:35:52
【问题描述】:

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

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

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

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

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

以下是我想出的其他一些可能的方法,以及我对每种方法的想法:

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

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

我现在如何拥有它对我来说是最有意义的,但是在我创建用户之前必须设置一个空所有者有点尴尬,然后在事后回来设置它。

如果您能给我任何意见,我将不胜感激。谢谢!

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

【问题讨论】:

  • 用户是否可以成为该帐户的所有者而不是该帐户的用户(即另一个帐户的用户)?
  • 不。帐户的所有者是它自己的用户,并且只是它自己的用户。

标签: mysql database-design data-modeling


【解决方案1】:

一般来说,如果您的架构无法进行拓扑排序,即如果您无法建立排序,其中表仅引用排序中位于其前面的表,则通常是一个坏主意。这种“分层”依赖也是一个非常好的属性,例如对于软件模块(如果两个模块相互依赖,就会出现问题)。

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

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

您知道(鉴于当前的请求)一个帐户必须有一个且只有一个所有者,或者一个用户必须列在一个且只有一个帐户中,这并不是真正与域相关的 IMO 规则。 “用户”和“帐户”。

您可以轻松实施这些规则,但是将数据结构化以使您没有其他可能性是 IMO 的错误。您的目标应该是为领域建模,而不是特定规则……因为人们会改变他们对这些规则是什么的看法。

你能设想一个有两个帐户的用户吗?您可以构思一个拥有多个所有者/管理员的帐户吗?我可以……这意味着很可能很快就会提出请求。结构化数据以使您无法表示这一点是在寻找麻烦。

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

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

【讨论】:

  • 这完全是我自己的项目,我将始终完全控制它,但我必须完全同意你所说的。当然可能有多个管理员(可以由 users 表中的布尔字段指定),我很确定用户只与一个帐户相关,但引入角色确实更有意义。我也喜欢你所说的为域构建数据,而不是特定规则。如果可能的话,我试图避免使用另一个表,但是您解释它的方式似乎更合乎逻辑。谢谢!
【解决方案2】:

你的解决方案很好。

如果您对所有者列可以为空感到不舒服,您可以依赖一些神奇的用户记录(可能 id 为零),这将是“系统用户”。因此,新创建的帐户将归用户零所有,直到它们的所有权被适当地重新定义。对我来说,这似乎比允许帐户拥有一个空所有者更臭。

【讨论】:

  • 是的,我同意——“用户 0”似乎更尴尬。我对空列没有真正的问题;我只是想确保没有任何我没想到的潜在问题会在未来出现。
【解决方案3】:

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

alter table UserAccount add constraint un_user_account unique(UserID);

当需求变为多对多时,放弃约束

alter table UserAccount drop constraint un_user_account;

仅适用于一个所有者,只需在应用程序级别强制执行即可。

【讨论】:

  • 感谢图表和示例,但这并不是我所需要的。我真的没有机会每个用户拥有多个帐户;如果我决定这样做,我肯定会像您那样使用第三张桌子。我主要只是询问记录哪个用户是帐户所有者的最佳方法。我认为只是一个布尔字段,类似于您所拥有的(users 表除外),但我认为让第三个表跟踪用户角色是最好的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-17
  • 1970-01-01
  • 1970-01-01
  • 2012-08-27
  • 2020-09-09
相关资源
最近更新 更多