【问题标题】:Is it sensible to have a table that does not reference any other in a database design?在数据库设计中拥有一个不引用任何其他表的表是否明智?
【发布时间】:2010-12-26 23:13:05
【问题描述】:

我想获得一些关于数据库设计的建议。具体来说,考虑以下(假设的)场景:

  • 员工 - 包含所有员工详细信息的表格
  • Users - 存放拥有用户名和密码以访问软件的员工的表格
  • UserLog - 用于跟踪用户何时登录和注销并计算的表 使用软件的时间

在这种情况下,如果员工离开公司,我还想确保将他们从Users 表中删除,以便他们无法再访问该软件。我可以使用ON DELETE CASCADE 作为EmployeesUsersEmployeeID 之间FK 关系的一部分来实现这一点。

但是,我不想从UserLog 中删除他们的详细信息,因为我有兴趣整理有关人们在软件上花费多长时间的数据,并且他们不再在公司工作这一事实并不意味着他们的用户行为不再相关。

我剩下的是一个表UserLog,它与我数据库中的任何其他表都没有关系。 这是一个明智的想法吗?

浏览过书籍等/在网上搜索过,我没有遇到任何带有与其他人没有关系的表的数据库模式,所以我的直觉是说我的方法不可靠......

请给我一些指导。

【问题讨论】:

    标签: sql-server-2005 database-design


    【解决方案1】:

    在这种情况下,我个人的偏好是通过在员工表中添加“DeletedDate”列来“软删除”员工。这将允许您维护 UserLog 表的引用完整性,并且所有员工(过去和现在)的所有详细信息都保留在数据库中。

    这种方法的缺点是您需要添加应用程序逻辑来检查活跃员工。

    【讨论】:

    • 或者您可以为在职员工创建一个视图并使用它来代替应用程序中的基表。
    • 有趣的想法。在这种情况下,对于大型组织而言,我的数据库中不会有大量冗余数据,即如果公司员工流动率很高,我最终会持有大量不再相关的数据,并且随着时间的推移会降低性能?
    • @Remnant:我工作的指导原则之一是:“在出现性能问题之前不要假设它们。”如果将来确实成为问题,您可以选择:您可以按照@HLGEM 的建议创建活动员工的物化视图,您可以查看表分区以便将活动/非活动员工分开,等等。
    • 感谢您的回答和进一步的回复。我将采用您的方法,因为我现在看到了其中的优点。此外,似乎大多数其他回复都和你说的一样,所以感觉清楚地表明这是最好的前进方式
    • 我使用“IsDeleted”位来执行此操作,因此我同意 Joe 的观点。我不一定会担心“冗余”数据或只是拥有太多数据;正如乔所说 - 在你遇到性能问题之前不要假设它们。但是,还有另一类问题可能支持删除辅助数据(例如,使用employees 表的PK 作为外键的其他表中的数据)。在我的系统中,我们经常查询这些表以获取聚合数据,并且我们不希望删除成员的数据。我们也不希望总是检查 IsDeleted 状态的开销。因此,我们确实会从引用表中删除记录。
    【解决方案2】:

    是的,这是完全明智的。日志只是对不应更改的数据的原始审计。它不需要被规范化(也不应该)和/或链接到其他表。

    理想情况下,我会将大量写入的审计日志完全放在与读取大量事务的日常事务不同的数据库中。随着时间的推移,它们可能会以不同的方式增长。但是,只要您了解它们之间的根本区别,就可以将它们保存在同一个数据库中。

    附带说明,我建议不要从表中删除用户。也许它们上有某种 IsActive 或 IsDeleted 位,这会有效地使它们无法使用应用程序,但应尽可能避免删除。

    【讨论】:

    • 谢谢。在你的最后一段,你为什么说应该避免删除?
    • @Remnant:在技术方面,这是一个昂贵的表操作,可能会强制索引重建等。但更重要的是,在业务数据方面,它摆脱了信息。也许在删除之前将其复制到某种存档数据存储中?在高度规范化的结构中,它还需要删除与该用户相关的所有内容,或者至少重新分配给虚拟用户,这两种情况都可能是不可取的。归根结底,数据保留是一项业务逻辑决策。但更倾向于一个以后可以改变的决定,而不是一个不能改变的决定。
    【解决方案3】:

    您在这里遇到的问题是,完全可以为从未存在的用户插入 UserLog 数据,因为没有指向定义有效用户的表的链接。

    我想说,也许更好的做法是将用户标记为无效并在他们离开时删除他们的所有个人详细信息,而不是完全删除记录。

    这并不是说在数据库中存在不引用其他表的表(或表)是无效的。

    【讨论】:

    • @Remnant,我不认为你的设计有问题,但戴夫对这个特殊情况的建议是一个很好的建议。您可以添加一个删除触发器来取消删除并执行更新以删除个人数据并按照建议将它们标记为无效。
    【解决方案4】:

    这是一个明智的想法

    问题是这样的。由于数据未链接,您可以从员工表中删除某些内容,并且在 UserLog 中仍然有引用。删除员工信息后,您无法知道日志数据与什么相关联。这个可以吗?技术上是的。没有什么可以阻止您这样做,但是您为什么要首先保留数据?您也不能保证表中的数据实际上是关于员工的。有人可能会在不属于任何人的表中意外输入错误的 EmployeeID。密钥有助于防止数据损坏。拥有额外的数据总是比拥有糟糕的数据要好。

    我发现,您永远不想在可能的情况下删除数据。空间很便宜,您可以添加标志等以显示记录未激活。是的,这确实会导致更多的工作(这可以通过创建一个只显示在职员工的视图来快速解决),并且说您永远不应该删除数据是牵强的,但是您开始将数据链接在一起。删除变得非常困难。如果您不是为了删除记录而添加 FK,那么这是您需要重新考虑策略的迹象。

    依赖级联删除也可能非常危险。您所说的模型是,只要您不想删除数据,就必须知道不要将 FK 添加到将其链接回用户的表中。很快就会有人忘记这一点。

    【讨论】:

    • (+1) - 我很感兴趣,因为大多数回复似乎都一致认为应该避免删除。除了“空间很便宜”的论点之外,这是为什么呢?说鬼话,删除记录肯定和更新和插入一样重要……?
    • 从技术角度来看,您是对的。我发现的问题是很多数据变得“交织在一起”,我的意思是这个 A 链接到 B 和 B 链接到 C 等等。数据有价值。公司使用它来决定如何运作。有时,法律需要拥有这些数据。名单还在继续。除了拥有档案系统之外,当您删除数据时,您是在断言现有数据依赖于已删除的数据,并且您永远不需要删除的数据。与没有它相比,节省和解决所需的时间和金钱是微不足道的。
    【解决方案5】:

    您可以做的是使用逻辑删除或通过将布尔值 Deleted 或 Disabled 添加到 Users 表来禁用用户。

    或者将 EmployeeId 替换为 UserLog 中的员工姓名。

    【讨论】:

      【解决方案6】:

      使用软删除过程的替代方法是在创建日志记录时存储您想要的有关用户的所有历史详细信息,而不是存储员工 ID。所以你的表中可能有用户名、登录时间、注销时间、会话长度。

      【讨论】:

        【解决方案7】:

        明智吗?当然,正如您所描述的那样,您需要无限期地保留这些用户是有道理的。您将遇到的问题是维护表格。您必须至少使用两次更新才能插入新用户,而不是进行一次级联更新。

        【讨论】:

          【解决方案8】:

          我认为您建议的表格非常好。我经常遇到与其他表没有明确关系的日志表。仅仅因为数据库是“关系的”并不意味着一切都必须相关哈哈。

          我确实注意到的一件事是您在日志中使用了EmployeeID,但没有将它用作Employee 表的外键。我理解你为什么不想要那样,因为你会解雇员工。但是,如果您完全删除它们,那么 EmployeeID 列就没有意义了。

          解决方案是为员工保留一个标记,例如active,以跟踪他们是否处于活动状态。这样,日志数据就有意义了。

          【讨论】:

            【解决方案9】:

            IANADBA 但实际上从数据库中删除几乎所有内容通常被认为是非常糟糕的做法,在您的用户表上拥有某种锁定标志/“已删除”日期戳并保留您的 FK 会更好。

            【讨论】:

              猜你喜欢
              • 2015-12-01
              • 1970-01-01
              • 1970-01-01
              • 2011-04-07
              • 1970-01-01
              • 2012-11-16
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多