【问题标题】:How do I relate one table to many different tables?如何将一张表关联到许多不同的表?
【发布时间】:2010-09-22 20:03:55
【问题描述】:

我有一个表格列表,即学生、教师、员工、部门。依此类推,这些表中的每一个都有特定于它们的 cmets。现在,表中的一条记录可以有一个或多个 cmets,这表明它是从任何表到 cmets 表的一对多关系。我不知道将 cmets 表与这些表相关联的最佳方法是什么。如果我将 cmets 表中的外键放入这些表中的每一个,它将像 40-50 个字段,具体取决于否。的表。其次,如果我将这些表中的每一个表中的外键添加到备注表中,就像为第二个备注外键重复整行一样?同样,如果我在每个表中只使用一个字段作为 cmets,我实际上将只在一个文本字段中存储行。有关如何实现有效解决方案的任何建议?

【问题讨论】:

    标签: mysql database database-design


    【解决方案1】:

    假设您的表(student、teacher、staff、dept)都有一个名为 Id 的 int 主键。

    对于您的 cmets 表,您可以创建一个表。

    Id int
    CommentType enum (student, teacher, staff, dept)
    LinkId int
    Comment
    

    评论中的一行可能如下所示

    1,'Student',347,'text'
    

    【讨论】:

    • +1 为问题的经典解决方案。实际上,我已经看到 Oracle 设计的数据库对数据库中的 all 表使用类似的结构。查询可能会有点混乱,但肯定会简化结构
    • 感谢您提供最有效的解决方案。我曾想过使用 varchar 作为表名,但我认为 Enum 是最好的。
    • 这种设计称为多态关联。我不推荐它,因为您无法使用真正的外键强制引用完整性。它也以几种不同的方式失败了规范化规则。
    • @Bill Karwin 请问您能提出更好的解决方案吗?
    【解决方案2】:

    由于这是一个多对多关系,您可能想看看使用关联表。

    使用您的示例,它可能看起来像这样:

    您的表可以拥有 cmets:

    +----------+------------+
    | student  | student_id |
    +----------+------------+
    | Steve    |         12 |
    | Larry    |         57 |
    | Sunshine |         88 |
    +----------+------------+
    
    +--------+---------+
    | dept   | dept_id |
    +--------+---------+
    | Math   |       2 |
    | P.E.   |       5 |
    | Drama  |      12 |
    +--------+---------+
    

    那么你需要跟踪实际的 cmets:

    +-----------------------+------------+
    | comment               | comment_id |
    +-----------------------+------------+
    | I love Math!          |          3 |
    | Larry is my hero...   |          5 |
    | Sunshine <3 Me!       |          6 |
    +-----------------------+------------+
    

    现在,您需要在这些表之间建立关联,这就是您的关联表发挥作用的地方。您现在可以关联哪些学生或部门有哪些 cmets,如下所示:

    +------------+------------+
    | student_id | comment_id |
    +------------+------------+
    |         57 |          5 |
    |         57 |          6 |
    +------------+------------+
    
    +---------+------------+
    | dept_id | comment_id |
    +---------+------------+
    |       2 |          3 |
    +---------+------------+
    

    这既有效又优雅。试一试!

    (也许还有一个问题)

    如果您担心拥有这么多关联表,当然可以只使用一个关联表,但我建议您不要这样做,因为它不那么整洁,并且消除了您可以在第一个中进行的引用完整性检查的一些可能性解决方案:

    +-----------+------------+---------+
    | entity_id | comment_id | entity  |
    +-----------+------------+---------+
    |        57 |          5 | student |
    |        57 |          6 | student |
    |         2 |          3 | dept    |
    +-----------+------------+---------+
    

    (这反过来会提示您为这些实体添加一个查找表......但我们不要去那里)

    【讨论】:

      【解决方案3】:

      您可以使用中间的“多对多”表。每个基表(学生、教授等)将有一个改变自我,存储基表的一个外键(例如 student_id)和评论表的一个外键。实际上,您的表格数量翻了一番,但您无需修改​​现有表格并获得完全的灵活性。

      【讨论】:

        【解决方案4】:

        如果您想保留外键约束,您需要有一个表来处理每个将具有注释子级的表的映射。

        意思是,Comment 将有一个主键,外键约束到每个处理映射的表。

        然后,在映射表中,您有 comment_id 和 ????_id 以及相应表的外键约束。

        【讨论】:

          【解决方案5】:

          您的 cmets 表可能如下所示:

          CommentID (int) - 主键 TableName (varchar(250)) - 注释相关的表 RecordID (int) - 引用的表中记录的 ID 评论(文本) - 实际评论

          您当然可以添加时间戳等可选字段,这样您就可以按照输入的顺序选择 cmets。

          现在您可以使用此表来存储任何表的 cmets,您可以通过过滤表名和记录 ID 来选择它们。

          【讨论】:

            【解决方案6】:

            是学生或教师或工作人员,而不仅仅是一种人..

            所以你有一个人,一个人可以有很多个cmets?所以你有一个与那个人有关系的 personcmets 表,为什么有一个备注表..是一个备注,而不仅仅是一种评论..

            如果没有更深入的架构,很难看到

            【讨论】:

              【解决方案7】:

              我的 50 美分:Zoredache 解决方案绝对不错,但我不鼓励使用枚举;它们在 mysql 中不是很聪明:如果您指定未知值,则错误将用空字符串表示 - 即使指定了一些默认值。此外,如果您想修改或添加新类型,则 ALTER 非常长。 unsigned tinyint 应该足以满足您的大部分需求...

              【讨论】:

              • 这个答案没有回答问题。这实际上是一种意见。您可能应该将其添加为评论。
              猜你喜欢
              • 2019-09-21
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-03-05
              • 1970-01-01
              相关资源
              最近更新 更多