【问题标题】:Can't decide whether normalization or de-normalization would work无法决定规范化或非规范化是否有效
【发布时间】:2017-03-05 19:47:37
【问题描述】:

这个问题可能有点宽泛!

最近我正在学习 MySQL。我正在制作一个学校考试信息数据库。我创建了一个名为 subjects 的表,其中存储了有关各种主题的信息,包括每个主题的全名或满分。我还创建了另一个名为 exams 的表,其中存储了每个学生在每个科目上获得的分数。显然subjects 是主表,exams 是这里的子表。根据存储在这两个表中的数据,当连接在一起时,会生成每个学生的百分比和成绩等信息。

但是如果subjects 表中的某些信息将来发生变化怎么办。假设某个特定科目的满分发生变化。在这种情况下,exams 表中的旧记录将无效或错误因为现在连接将生成对当前记录正确但对旧记录错误的新值。

在这种情况下我该怎么办?我是否将两个表非规范化为一个完整的表?但是我在数据库设计方面的胆怯知识表明这是错误的做法!

任何帮助或见解都将受到高度赞赏。

【问题讨论】:

  • 临时表怎么样
  • 您能详细说明一下吗?我在听。
  • 据我所知,到目前为止,您有 3 张桌子,而不是 2 张。学生、科目、考试。保持东西标准化并有相交表。见Junction tables
  • 太棒了。那会让我继续前进。非常感谢!
  • 搜索“历史数据”。例如stackoverflow.com/questions/3874199/…

标签: mysql database-design


【解决方案1】:

您可以在subjects-表中添加新行,而不是在主题更改时更改现有行。因此,主题表包含主题的版本。这可以与使用有效日期结合使用。应用该方法后,您将需要一个标准化步骤。这可能是其中一个 cmets 的含义。

【讨论】:

  • 感谢您的解决方案。从来没想过。但我在想,这不是意味着在subjects 表中重复相同的数据吗?因为除了满分之外,其他列数据如主题名称和主题类型会重复很多次......或者这无关紧要。
  • @TamonashGupta Re“那不意味着重复”:是的。如果这是一个已证实的问题,请参阅我的回答。
  • 这就是我在答案中添加以下句子的原因:“应用该方法后,您将需要一个规范化步骤。”因此,您可以将主题拆分为两个表格。
【解决方案2】:

您需要为您的历史情况建模,就像您为当前情况建模一样。

您可以选择也可以不选择非规范化过去的数据。但每次努力的最大好处实际上涉及使历史情况表看起来像或实际上是当前情况表。这涉及投资进一步规范化当前行到子行中,然后将其扩展一个日期,以便您可以将同一日期的子行连接在一起。

如果重复的数据是/成为一个明显的负担,那么您可以将一个表拆分为多个表,用于您希望为最近更改的日期而其他子行保持日期为较早更改的子行。然后,您可以连接到给定日期为止一致的最新行。在一些“时间”数据库中,我们通过将行拆分为子行来最小化冗余数据,而不只是对它们进行约会,而是用它们当前所在的日期范围来标记它们。

来自a recent answer of mine

硬删除建议假设您保留了所需的历史数据。不要将实现这一目标的想法限制在仅将 FK 归零、级联、将标志/日期列添加到现有表或其他任何事情上。正确建模现在和过去,包括在每个选择的应用程序情况发生变化时需要作为 DBMS 事务发生的数据库更改。软删除的建议只是将某些当前和历史数据放入同一个表而不是不同的表中。这仅适用于当前和历史情况的非常简单的模型。

仅针对当前应用情况设计数据库通常很简单。但是,如果我们确实关心过去,我们通常只关心其中的一部分。如果是这样,在某些应用程序情况从当前变为过去时,我们可以将相关当前状态的快照复制到历史状态。使用软删除标记与日期标记数据是未注明日期与已注明日期的历史数据的组合表版本,我们只关心当前和过去的情况,并且只关心发生变化的时间。

“时间”数据库或多或少地记录了当前的情况和一堆过时的曾经的当前情况。这种使用当前数据结构的过去数据记录简化了对当前和过去数据的理解和查询。 (查询时态数据库可以促进的时间间隔可能会变得相当复杂。)但事实证明,制作给定当前数据设计的时态版本不仅仅涉及将日期列添加到现有的当前数据表中。它需要对当前数据进行重构,将其分解为具有更多约束的较小表。这是因为不同类型的应用情况变化需要对现有当前数据设计的不同列组合进行约会。 (硬历史快照设计和软历史快照设计必须解决这个问题,但仅限于有限的过去/历史。)

【讨论】:

  • 感谢@philipxy 的洞察力。就我而言,设计和编程历史数据可能过于复杂。因此,正如您在某处提到的“只有非常简单的案例才能通过某些位是否处于活动状态而逃脱”,我现在将简单地标记我的记录。
  • 再想一想,您能否举例说明如何根据您的建议对历史情况进行建模。我想学这个。
  • 我的建议是决定你想要记录的当前和过去的内容。你的问题基本上是说,'如果我做 X,我不会得到我想要的'。所以不要做X。找到你想要的东西的方法是设计。现在:使用当前数据 student(id, name, addr)。对应用情况进行一系列更改。当你去问过去却得不到你想要的,重塑现在和过去。尝试当前标志、版本号、日期和/或复制(子)行。添加类(id,名称)和考试(sid,cid,mark)并重复。
  • 好的,我正在尝试。我目前正在使用isactive 列来标记我的subjects 表中的新旧记录。相应的程序会查找isactive = true所在的记录,从而分别识别新记录。
猜你喜欢
  • 2013-08-21
  • 2016-05-13
  • 2018-06-06
  • 1970-01-01
  • 2013-01-18
  • 2021-06-13
  • 2012-10-08
  • 2010-12-29
  • 2020-04-06
相关资源
最近更新 更多