【问题标题】:Person name structure in separate database table单独数据库表中的人名结构
【发布时间】:2010-11-13 00:04:18
【问题描述】:

当数据结构出现在多个表中时,我想知道何时以及何时不将数据结构拉入单独的数据库表中。

我已将 12 属性地址结构提取到单独的表中,因为我有几个不同的实体包含这种格式的单个地址。

但是我的 3 属性人名结构(给定、中间、姓氏)怎么样?

是否应该将其放入其自己的表中,并为包含名称的所有实体使用外键引用...例如company 表有一个联系人姓名,citizen 表有一个人名等。

这些最好作为属性保留在主表中还是应该将它们提取出来?

【问题讨论】:

  • 请注意,我所说的组合是指这些数据结构只能作为整体的一部分存在,没有其他表可以指向同一个实例。

标签: database database-design


【解决方案1】:

我通常会将地址保留在 Person 表中,除非每个实体非常需要绝对统一的地址,或者如果一个实体可以有任意数量的地址,或者如果需要在实体之间共享地址,或者如果它是一个大型企业产品,我知道我必须在整个地方投资基础设施,否则我最终会毁掉一切。

将您的地址放在单独的表格中很有趣,因为它很灵活,但是在像上面提到的那样缺乏特殊需求的小型项目的情况下,这可能有点浪费。始终注意复杂性和灵活性之间的平衡。灵活性很重要,但要区别对待...在那里很容易投资太多!

具体来说,在我尝试(例如)一对一关系(例如地址)时,我最终将它们重构回表中,因为它引入了一系列令人头疼的问题,包括更复杂的查询、处理在地址不存在的情况下,等等。更多的实体也会增加你的认知负担——这会使项目更难思考。就我而言,这是不必要的成本,因为没有具体的需求,事实上,甚至没有获得灵活性。

因此,根据我的经验,我会“尝试”将地址保留在同一张表中,并且我肯定会保留名称 - 再次重申,除非有特殊需要。

所以套用爱因斯坦的话说,让它尽可能简单,不要更简单。但在短期内,进行实验。这是学习这些课程的最佳方式。

【讨论】:

  • 地址格式绝对统一,每个实体只有一个地址,没有共享地址,是大型企业解决方案。但是,如果每个实体都指向地址实体中的一个地址,我就失去了当一个实体被删除时地址会跟随的保证。从地址实体指向另一个实体是不切实际的,因为它们的主键格式不相同。
  • 好吧,如果你最终建立了一对一的关系,我感觉你将无法级联删除。您可能必须使用对我来说并不理想的触发器。你可以设置一个一对多,但是你最终会得到一堆可以为空的键等等,如果你真的想打破它,这可能没问题。我已经完成了一次日志记录,这没关系——我有一个日志记录结构,它为用户和其他一些外键提供了可为空的外键。它似乎工作正常。你必须明白,即使是一对多,现在每个人只有一个地址。
  • 您实际上可以将其视为增加了灵活性...例如,也许在以后您实际上会想要引入更多地址。这样,结构已经到位。但是,与此同时,与仅在 Person 记录上相比,使用它会更难一些。
【解决方案2】:

这是关于不重复信息,所以你不想在两个地方存储相同的信息。

另一个有用的经验法则是每个表一个实体。如果您发现一张表包含“person”和“order”,那么您可能应该将它们分成两张表。

而且(让自己面临重复信息的风险...)您可能会发现复习一些数据库设计基础知识很有帮助,stackoverflow 上有很多相关问题。

从这些开始...

What is normalisation?

What is important to keep in mind when designing a database

How many fields is 'too many'?

More tables or more columns?

【讨论】:

  • 但是由于新的 PersonName 表行是用外键指向的,所以 PersonName 信息不会仅仅通过删除 Company 行或 Citizen 行而消失。然而,它的存在只能通过这些指向行的存在来证明。
  • 只为 PersonNames 拆分一个单独的表会很浪费。 ;) 但是如果你这样做了,你可以使用 Cascade Delete,这样当 Person 被删除时,数据库会删除相应的 PersonName。在 SQL Server 中,这是关系的一个选项。
  • 现在,如果这个 PersonName 被几个不同的东西使用 - 比如说 PersonNameID 5 是 Brian MacKay 并且它出现在 PersonID 200 和 CitizenID 120 中,你不能再删除 PersonID 200 因为级联会失败.所以:要么将 Person 和 Citizen 合并到一个表中,要么通过不将名称结构分解为单独的表来简化您的生活,或者两者兼而有之。我建议两者都做。
【解决方案3】:

在您的数据模型中创建个人实体将为您带来当前和未来的优势 -

  1. 作为联系人出现的同一个人,或不同上下文中的个人。节省冗余。
  2. 信息可以轻松维护并保持最新状态。
  3. 更容易搜索和识别一个人 - 即他是 John Smith 吗?
  4. 您可以扩展信息 - 即更轻松地维护此人的地址。
  5. 编程将更加一致,调试也将更加轻松。
  6. 让您更接近“自我记录”系统。

【讨论】:

  • 要非常小心,你的实体在语义上是相同的,不要碰巧在这个时间点具有相同的属性......
【解决方案4】:

作为与其他(完全有效)回复的对比:在您的应用程序的当前结构中,给定个人(不仅仅是姓名,实际的“人”——多个人可能是“约翰·史密斯”)的可能性有多大) 出现在多个表中?这种情况发生的可能性越小,您从标准化中获益的可能性就越小。

另一种思考方式是实体。在标签(名称)之外,“客户”实体和“员工”实体之间是否有任何重叠?

【讨论】:

    【解决方案5】:

    提取它们。您的目标应该是在您的数据库中没有重复数据。 阅读Normalization

    【讨论】:

    • 你知道,像名字/姓氏这样的东西,不一定是重复数据,而是重复数据结构。对我来说,只要你不重复数据,重复这些结构是可以的。在简单性方面的权衡是值得的。
    • 不,这很好。问题是当您在整个数据库中复制同一客户时,即“Brian MacKay”出现在每个表中。没有办法将此用户合并为单个用户(可能有多个您购买)。
    • 是的,正是丹丹。所以你想使用 PersonID 5,也就是 Brian MacKay,作为你的外键。我想不出在很多情况下您会想要使用 PersonNameID 2030。您可能最终想要获取一些 Person 数据,并且您必须向后工作以找出 Name 属于哪个 Person。不必要的头痛。
    【解决方案6】:

    这实际上取决于您要解决的问题。一般来说,拥有某种保存人员详细信息的“人员”表可能是一个好主意。但是,在某些情况下,这可能是一个非常糟糕的主意。

    例如,如果您持有医生开给人们的处方的详细信息。在某些国家/地区,法定要求是处方详细信息以开具处方时使用的姓名而非患者当前的姓名保存。例如,某位女士可能被开为 X 小姐,但随后她结婚并成为 Y 夫人。如果您有一个与处方表相关联的人员表,您现在将获得错误的详细信息,并可能面临法律后果。在这种情况下,您可能需要将人员的相关详细信息复制到处方表中,即使这会重复数据。

    再说一遍 - 这取决于您要解决的问题。不要盲目地遵循人们认为的最佳实践。了解您的数据及其相关的任何问题,然后尝试遵循适合的最佳做法。

    【讨论】:

      【解决方案7】:

      取决于您使用数据库的目的。

      如果您想对表进行快速查询,您应该对表进行反规范化。必须运行多个 JOIN 将花费更长的时间,并使您的查询更加复杂。

      另一方面,如果您的意图是拥有一个灵活的存储数据库,并且不会受到大量快速响应查询的影响,那么通过将表拆分为多个外部参照表来规范化表将提供更多设计灵活性并减少提交重复数据的需要。

      由于反规范化是“优化”,我建议您首先对表进行规范化,正确索引它们,看看您的查询是否遇到任何瓶颈。如果是这样,请在需要的地方展平受影响的表。

      【讨论】:

        【解决方案8】:

        你真的应该考虑你的整个数据库结构,首先做一个ER图(实体关系图)。当然应该有另一个名为“Person”的表,其中存储了一个人的概念......

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-04-05
          • 2021-01-13
          • 2012-02-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多