【问题标题】:Modeling Relational Entities for Auditing Question States为审计问题状态建模关系实体
【发布时间】:2010-09-25 13:42:13
【问题描述】:

这让我怀疑了一段时间,所以我认为将它发布在这里以找到一些见解是个好主意,这是一个关系数据库建模问题/怀疑

我有以下问题:

我有必须处于特定“状态”的“问题”,并且必须审核所有状态更改。

我找到了两种解决方案,但我看不出它们之间的区别,如果有的话......你怎么看。

这是包含两个图表的图像。

编辑:

选项 A:表“questions”不应包含 state_id,并且 Question_State 不应包含“id”字段。对错误深表歉意。

EDIT2

感谢所有现实世界的例子和洞察力,但这是一个学术问题,与现实世界无关:)。

【问题讨论】:

    标签: database-design relational


    【解决方案1】:

    我认为您要问的要点是:问题的状态是否应该基于 Questions 和 State 之间的具有时间分量 (A) 的中间表,或者该表是否应该更加静态,但具有(B) 侧的面向日志的历史记录表。

    (注意:如果你想做一个纯版本的 (A),那么 Boofus 是对的,你可能不会把 state_id 也放在 Questions 表中,因为它是多余的;但这肯定不方便,因为它会使简单的查询更难获得特定状态的问题。所以这里有一个混合版本。)

    一般来说,如果保留有关状态的历史信息的要求真的只是为了审计目的 - 也就是说,如果应用程序本身不会定期查询它 - 你可能最好选择选项 B,因为它更简单一些(实际上只有一个“问题”表,有一个状态参考表,以及一个用于先前状态的“日志”表)。我认为这更好地表明了你的意图。

    但是,如果应用程序语义更复杂(例如,如果您有诸如“显示过去 24 小时内处于状态 X 的所有问题......”之类的查询),那么类似 (A) 的方法可能会使更有意义。它本质上是把一个问题的状态变成一个与时间相关的事实。如果您这样做,请注意它会使事情复杂化 - 要么您的所有查询都更难并且必须考虑时间,或者您必须担心保持 Questions 上的 state_id 与 Questions 表中的最新状态同步。如果你走那条路,也许可以在 Questions 上将其称为“current_state”或其他名称,因此很明显它是一种衍生信息。

    【讨论】:

      【解决方案2】:

      您可能想在网络上搜索“时态数据库”这一主题。基本上,存储任何变量的变化历史都会引发同样的问题,无论该变量是否捕获问题状态或人的体重等。

      其次,我认为您的问题与数据库设计有关,与概念数据建模无关。如果我猜对了,你就是在问哪种桌子设计更好。

      第三,我更喜欢选项 B,但这实际上取决于您将如何处理数据。

      我询问数据库设计与概念建模的原因是,我很久以前就采用了使用“实体和关系”进行与数据分析相关的概念数据建模的做法。在讨论逻辑数据库设计时,我使用术语“表、列和行”。将分析和设计分开在大型项目中非常有价值。而且做起来并不像听起来那么容易。

      对于选项 B,您确实应该在图表中的历史表和状态表之间添加一个箭头。图表的呈现方式几乎看起来就像历史表是一个不相交的表。在这个简单的示例中不是问题,但是如果您在扩展到具有数十个表的数据库时保持相同的做法,您最终会混淆查看图表的每个人。

      【讨论】:

        【解决方案3】:

        一旦你绘制了所有的关系,它们都是一样的。

        我不明白为什么你在问题表中有 state_id - 因为你有历史表,所以在问题表中拥有状态是多余的,并且可能会给你留下不同步的数据。

        在我看来,如果你想要一个问题的当前状态,你会这样做

        SELECT State_ID FROM Historical WHERE Question_id = ? ORDER BY Date DESC LIMIT 1

        (或您的 SQL 风格使用的任何限制为 1 行的方法)

        【讨论】:

        • 这使得像“SELECT * FROM Questions WHERE status = 'X'”这样的查询更难编写。
        【解决方案4】:

        假设您在数据库和 OO 之间有良好的抽象层,您可能会考虑将 State 表从数据库中取出并使其成为类中的枚举。这不一定是需要持久化的东西。

        然后在 Questions 表和 audit 表中添加 State 列。

        【讨论】:

          【解决方案5】:

          您说已审计,这意味着您只是希望保留历史信息以用于报告目的。在这种情况下,我建议图 B 更清晰,尽管您可能应该标记 Questions 和 Historical 以及 State 和 Historical 之间的一对多关系。

          至于实用性,如果情况如上所述,我本人会将历史插入功能封装到问题上的插入/更新触发器中,并且如果问题表的数量和/或状态更改的数量将很重要我会考虑将历史表放在不同的数据库中。这只是简化了以后的数据库管理。通常我对触发器持谨慎态度,因为过度使用会导致数据库难以维护(因为目前还不清楚发生了什么),但这是一个明显的例子,它们非常适合并且是使用的更好选择应用逻辑。

          顺便说一句,您的两个图表都暗示一个问题只能进入每个状态一次(来自您的 PK) - 您应该考虑这是否正确,因为在大多数现实世界的应用程序中都会犯错误并反转状态。

          【讨论】:

            【解决方案6】:

            我不明白,像 #Boofus 一样,在 Questions 表中包含 state_id 字段的兴趣。

            我一直在我们自己的应用程序中使用此类“状态”概念进行了大量工作。在最复杂的情​​况下,我们必须跟踪完整的状态历史以及对象可以具有多个状态的情况,我们使用以下模型:

            对于多状态情况,想法是检查 end_date 值是否为空(另一个想法是在表中有一个布尔字段 isActiveState)。不要低估拥有这种“多态”配置的兴趣。示例:

            一个问题可以是

            • 关闭并解决

            • 已关闭且未解决。

            这可能对应于两种不同的状态:

            • “关闭并解决”状态

            • “已关闭且未解决”状态

            但我认为最好的解决方案是同时拥有一个

            • “打开/关闭”状态

            • “已解决/未解决”状态

            并允许问题有多个状态

            【讨论】:

              猜你喜欢
              • 2013-11-27
              • 1970-01-01
              • 2021-07-15
              • 1970-01-01
              • 2013-06-28
              • 1970-01-01
              • 2018-06-22
              • 2023-04-03
              相关资源
              最近更新 更多