【问题标题】:Database Design, Table emulating foreign keys to multiple tables数据库设计,表模拟多个表的外键
【发布时间】:2012-05-28 06:59:45
【问题描述】:

我正在尝试解决一个问题,但很难找到最佳解决方案。我有一个数据库,其中包含(除其他外)以下内容的表:

  • 目标请求
  • 支持请求
  • 交换请求
  • 存款申请

这些表中的每一个都有一个 cmets 列(从最终用户到管理员),但是我被要求添加向所有这些请求添加注释的功能。我希望每组笔记都是分开的,这样我就可以跟踪添加笔记的日期/时间,以及谁编辑了它。这表明我需要将注释存储在表格中,并通过外键链接回请求。问题是每个请求表都有一个自动递增的 id 列,该列在该表中是唯一的,但对于所有其他表来说不是唯一的(这意味着每个表都可以有一个 id 为 200 的请求)。

我意识到我的问题的一个解决方案可能是为每种类型的请求创建一个“Notes”表并相应地创建外键,但这肯定不是解决问题的唯一体面方法。

我真正想知道的是是否有一种有效的方法可以使用 id 和请求类型(基本上是表名)来创建外键。这可能吗?

【问题讨论】:

  • 除了 ID 和 cmets 之外,这些表是否有任何共同的属性?
  • 一般来说,将元数据与真实数据一起存储是个坏主意。将参考表与参考 ID 一起存储不会像拥有多个表那样工作。
  • @Keyser:它们每个都有一个指向 User 表的外键,并且它们每个都有一个 RequestDate 和 RequestStatus(我想它们都有一个 RequestID),但除此之外,它们的存储非常棒不同的数据。
  • @JNK:我大部分同意。我只是想知道是否有另一种解决方案可以提供公平的数据完整性并为我节省 3 或 4 个表来管理。
  • @BrendonDugan 最好有更多的桌子。考虑您的源表更改的可能性 - 假设您出于必要向 Destination 的键添加另一个字段 - 您需要以非常复杂的方式重建整个 cmets 表。

标签: sql sql-server database-design foreign-keys ddl


【解决方案1】:

您可以有一个表 Note( object_id, note ),其中 object_id 引用任何请求表。您实际上不必在数据库中有外键约束,或者如果您真的想维护一个约束,您可以使用约束子句(可能是特定于供应商的?)。

要确定注释与哪个请求表相关联,您可以在 Note 中设置一个枚举类型值。一些数据库供应商有一个 Enum 类型,其他你可能只使用一个 Int。它只是像 request_type enum(DESTINATION, SUPPORT, etc....) 这样的列。

如果您的数据库很小或可以离线一段时间,您可以改为重新创建表,以便它们使用单​​个序列来生成它们的所有四个 object_id...这样 ID 将在不同的请求表。对于这种情况,我喜欢有一个普遍唯一的 object_id 序列。

对于某些供应商(postgres),您可以使用表继承。使用表继承,您可以执行类似 create table destination_request(....) inherits(note);这将使 note 表中的任何字段可用于对 destination_request 表的查询。从某种意义上说,这确实有效,并且在幕后为您完成了工作。从概念上讲,请求不是注释的子类型,因此这在 OO 设计方面并不理想,并且表继承可能无法移植到其他数据库供应商。在这里,您对纯度的关注程度取决于您。

如上所述,您可以有四个不同的外键指向每个表,但这会给您留下一个大部分为 Null 值的表...我可能更喜欢拥有四个不同的笔记表而不是拥有一个包含这么多空值的表.

【讨论】:

    【解决方案2】:

    作为创可贴,你可以做这样的事情......

    ...对Note 有以下约束:

    CHECK (
        (
            “Destination Request Id” IS NOT NULL
            AND “Support Request Id” IS NULL
            AND “Exchange Request Id” IS NULL
            AND “Deposit Request Id” IS NULL
        )
        OR (
            “Destination Request Id” IS NULL
            AND “Support Request Id” IS NOT NULL
            AND “Exchange Request Id” IS NULL
            AND “Deposit Request Id” IS NULL
        )
        OR (
            “Destination Request Id” IS NULL
            AND “Support Request Id” IS NULL
            AND “Exchange Request Id” IS NOT NULL
            AND “Deposit Request Id” IS NULL
        )
        OR (
            “Destination Request Id” IS NULL
            AND “Support Request Id” IS NULL
            AND “Exchange Request Id” IS NULL
            AND “Deposit Request Id” IS NOT NULL
        )
    )
    

    这样,您不必更改现有表的 PK(这可能会对模型的其余部分和客户端应用程序产生级联影响),而无需“重复” Notes 表。

    【讨论】:

    • 这似乎是最好的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2010-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-13
    • 2014-07-09
    • 2011-10-23
    • 1970-01-01
    相关资源
    最近更新 更多