将附加要求纳入遗留数据库设计
Posted
技术标签:
【中文标题】将附加要求纳入遗留数据库设计【英文标题】:Incorporate additional requirements into a legacy database design 【发布时间】:2013-12-15 16:30:17 【问题描述】:我正在为数据库设计而苦苦挣扎,这就是我目前所拥有的。
这里有问题。
我需要引入一种新的用户类型(企业集团经理),他们将了解公司集团(企业集团)。一个集团经理可以拥有多个公司,一个公司可以属于多个集团经理。如果可以添加一家独立公司,然后在以后轻松地被纳入企业集团的一部分,那将是有利的。
我发现这很难建模,因为到目前为止我的所有用户(经理、司机、收件人)都存在于 users 表中。这是设计使然,因为它们都具有几乎相同的数据字段,并且我需要为我网站上的所有用户提供一个登录点。如果我在 users 表中添加一个 conglomeration manager,他们将与我现有的用户类型没有的其他表建立关系。
我对通过用户、所有权、包、公司、用户形成的依赖循环感到不安。这给我的印象是不好的形式,但我真的想不出一种方法来避免它:
经理、司机和收件人都为一家公司工作。该公司有一组相关联的包裹,但我需要能够将这些包裹的子集与特定收件人(他们拥有包裹)和特定司机或经理(负责交付这些包裹)相关联。
我对用户中的“receive_emails”字段不满意,因为它只与“收件人”类型的用户相关。
更糟糕的是,这种设计已经在使用中,并且必须将数据迁移到任何新的设计中。
系统中最常见的操作是收件人查看状态,然后是经理和司机创建状态。
优雅的新设计可以解决我的问题吗?
【问题讨论】:
您需要将其分解为一个问题。这对这个论坛来说太宽泛了。 从您在第 1 段中所说的,您将需要用户和公司之间的多对多关系。 不用担心将列移动到不同的表。是的,迁移会更困难一些,但您将使用数据库设计数十年。 @Dan - 这会有所帮助,但这种关系对于某些用户来说没有意义。例如,收件人仅属于一家公司。 @Gilbert - 同意,现在值得拥有它。 【参考方案1】:好吧,这是另一个尝试。我还是觉得
您不必太担心 receive_emails 字段,正如我在其他答案中所解释的那样。 您不必将用户划分为用户类型。您在 2 中担心的是依赖关系。依赖关系通常不是问题,但是您在基于 id 的数据库设计中非常严格,因此从您的 dbms 中隐藏了依赖关系。如果它知道,它可以帮助你:-)
你可以这样做:
坚持使用“users”表,但删除 company_id。 您不必对“公司”、“包”、“参与”和“状态”进行任何更改。 添加一个表格以将用户链接到公司。让我们暂时称该表为“从属关系”。 (我不知道这是否是一个合适的名称,我的英语在这里失败了。)就像所有权一样,这只是一个链接表,所以唯一的字段是 user_id 和 company_id(形成主键)。 现在将 company_id 添加到“所有权”。 (我知道,由于您指向“包”的链接,它有点隐含,但 dbms 不知道。)所以添加该字段,现在您的 dbms 看到该字段,您还可以添加一个约束(外国key) 在 package_id 加上 company_id 到“packages”,以及对 user_id 加上 company_id 到“affilations”的约束。就是这样。您没有太大变化,但现在一个用户可以隶属于许多公司(到目前为止是企业集团经理,但也许有一天您决定允许接收者与多家公司合作,或者让司机在同一时间为多个公司工作时间)。并且现在“所有权”中不存在错误条目的风险或对内容和使用有任何疑问。
如果您想安全地使用您的 receive_emails 字段,您可能想采用以下方法(正如我所说,这并不是真正必要的):创建一个包含两个字段的新表 email_recipients:user_id 和 user_type。是的,又是冗余。但是这样做,您可以对 user_type 进行限制,只允许某些类型(到目前为止只有“收件人”)。同样,您不仅会拥有 user_id 的外键,还会拥有 user_id 和 user_type 的外键。
【讨论】:
【参考方案2】:我需要引入一个新的用户类型
在这些类型的场景中,当需要添加新类型时,这会导致架构重组,导致我在设计上出现缺陷。
实际上管理和驾驶是用户扮演的角色,可能会随着时间而改变。
现实中:
用户不是经理(他是个人)。
管理角色扮演用户。
考虑一下公司是否决定拥有帮助台用户。
我将添加Role
和User-Role
表来保持用户和角色之间的关系。
我对用户中的“receive_emails”字段不满意。
在User-Role
中有receive-email
字段将是一个选项。
我需要为我网站上的所有用户提供一个登录点
在登录页面上选择用户、公司和角色可能会有所帮助(这将对您的应用程序设计产生直接影响)。
我对通过用户形成的依赖循环感到不安, 所有权、包、公司、用户。
从概念上讲,我们将拥有接收者用户 => 所有权 => 包 => 公司 => 驱动程序或经理用户。 顺便说一句,它是一个关系模型。
企业集团。
【讨论】:
【参考方案3】:3:不要太担心 receive_emails 字段。请记住,您的数据库只是现实世界的一个模型,不一定是完美的。是的,您可以将“收件人”设为自己的表格。考虑一下你会得到什么,你会失去什么。事实上,这不是一个糟糕的设计。如果用户不是收件人,您可以使用触发器将 receive_emails 设置为 false。或者使用视图来隐藏与司机或经理打交道的应用程序的字段。随你喜欢。好吧,如果你真的想摆脱这个字段,你可以有一个表“emeil_recipients”,其中包含所有作为电子邮件收件人的用户 ID。你看有很多方法可以解决这个问题,它们都有自己的优点和缺点。你的设计很好。
2:据我了解,每个包裹最多有一名经理、一名司机和一名收件人。是这样吗?那为什么还要有一张“所有权”表呢?在“包”表中放置三个字段; user_id_driver、user_id_manager、user_id_recipient。所以你的模型更接近现实。 (您可以在迁移期间创建一个视图“所有权”来替换表“所有权”。)
1:现在到企业集团。最简单的方法是引入两个新表:首先,您将有一个表“company_groups”,其中包含一个 id 和一个描述字段。您的表“users”将有一个字段“company_group_id”,它将替换字段“company_id”。因此,您将用户链接到公司组而不是单个公司。您的第二个新表将是“company_group_members”,只有两个字段,id_company_group 和 id_company。您将建立仅由一家公司(针对经理、收件人和司机)组成的“组”和由更多公司组成的组(针对集团经理的集团)。因此,您的数据库不会发生太大变化,但会提供您所需的一切。
说了这么多,您仍然可以考虑将表“users”减少到公共字段,并让新表“managers”、“recipients”、“drivers”和“conglomeration_managers”包含其他字段。这使您更接近现实,并使包的链接更清晰。但是,这是以与您当前的模型不同的模型为代价的。如果您以后添加副驾驶员、秘书或其他任何东西怎么办?每次新表换新工作?再说一遍:有很多方法可以构建您的模型。选择最适合您的。
我希望我的建议可以帮助您全面考虑。
【讨论】:
WThorsten - 感谢您的回复。 “据我了解,每个包裹最多有一位经理、一位司机和一位收件人”——不,一个包裹可能与这些用户的多个相关联。 好吧,我再考虑一下。所以在你的系统中有可以登录的用户。这些是公司的经理,为公司工作的司机,不属于公司但从一家且只有一家公司获得东西的收件人?然后是企业集团经理,每个人管理一个或多个公司。除了这些,没有其他用户。到目前为止? 重新考虑之后,我决定写一个新的答案,而不是更改现有的答案。尽管您仍然可以将它们结合起来,但我认为我的新答案很好地解决了您的所有问题,您可以忘记我的第一个答案:-)【参考方案4】:扩展用户!
就像扩展一个类一样,您可以创建一个新表“Managers”,其中包含更多列和一个针对用户的 FK。
因此您可以创建经理和公司之间的关系表。
如果您想更好地控制该集团实体,请创建集团表并为经理创建一个 FK,这样您就可以在集团和公司之间创建一个关系表,或者如果一个公司不能由两个集团拥有,则只需一个公司的 FK合并。
【讨论】:
感谢您的回复!这听起来是个好主意。对问题 2 有任何想法吗? 同样的答案:扩展用户!您可以创建扩展用户表的收件人和驱动程序表。不要因为可能的循环而感到不安,因为用户不一样,所以不会发生。 好吧,如果司机可以晋升为经理,或者经理可以为自己送货,它实际上可以循环,但我不认为这是一个问题。不管怎样,你已经做了最艰苦的工作,创造概念。如果场景是上帝的(与现实和业务逻辑相一致),只要坚持你的数据设计就可以了。以上是关于将附加要求纳入遗留数据库设计的主要内容,如果未能解决你的问题,请参考以下文章