【问题标题】:multiple tables need one to many relationship多个表需要一对多关系
【发布时间】:2011-07-29 02:38:01
【问题描述】:

我有一个包含多个表的 SQL 数据库:A、B、C、D。这些表中的实体是完全不同的事物,具有不同的列,它们之间的关系也不同。
但是,它们都有一个共同点:需要一个评论系统,在这种情况下,它具有相同的结构:作者 ID、日期、内容等。

我想知道哪种策略最适合此架构让 A、..D 表使用注释系统。在经典的“博客”网站中,我会使用与“cmets”表内的 post_id 的一对多关系。

这里看起来我需要一个 A_cmets、B_cmets 等表来处理这个问题,这看起来有点奇怪。

有没有更好的办法?

【问题讨论】:

  • 旁注:表没有关系,它们关系(或者至少,如果 SQL 正确实现了关系模型,它们会是关系)。他们之间的关系是关系
  • @Marcelo,有趣的一点,你能扩展一下吗? (虽然我的英语很好,但这不是我的母语)。表本身是如何关系的?
  • 这不是真正的英语,而是数据库术语的问题。 relation 是关系模型中一个非常具体的概念(非正式地,一组带有标题的元组);它在 SQL 中的对应物是表。当您提到表之间的“关系”时,您真正的意思是外键,这是表之间约束的一种特殊情况,可以随便称为关系。但应避免使用“关系”一词,以免与该词的正式含义混淆。
  • 关系这个词来自数学。这是一组有序的元组。数据的关系模型源于关系的数学。使用单词关系来表示表之间的关联有助于清晰。这在其他语言中可能会有很大不同。

标签: sql database-design


【解决方案1】:

对于更多不同的对象类型(例如,在我的情况下,文章和商店,每种类型都有自己的表),我在 cmets 中遇到了类似的“问题”。

我做了什么:在我的 cmets 表中,我有两列管理链接:

  • object_type (ENUM type) 确定我们要链接到的对象/表,并且
  • object_id(与其他表(或其中最大的表)的主键匹配的无符号整数类型)指向特定表中的确切行。

则列结构为:idobject_typeobject_idauthor_iddatecontent

重要的是在两列(object_type, object_id) 上都有一个索引,以加快索引速度。

【讨论】:

  • 很好,我搜索了半解决方案,但我想保持我的数据库规范化,知道如何管理 thouse 表之间的关系吗?
【解决方案2】:

我假设您说的是单个 cmets 表,其外键“恰好是”A、B、C 或 D 之一。

SQL 无法处理这一事实是其根本弱点之一。这个问题被一遍又一遍地问到。

见,例如

What is the best way to enforce a 'subset' relationship with integrity constraints

您的约束是从“单个 cmets”表到视图中的“外键”,它是 A、B、C 和 D 中的标识符的并集。SQL 仅支持基表中的外键。

请注意,SQL 作为一种语言确实以 CREATE ASSERTION 的形式支持您的情况。但是,我知道没有支持该语句的 SQL 产品。

编辑 您还应该记住,对于“单个” cmets 表,您可能需要在 A、B、C 和 D 中的键之间强制执行不相交,否则有时可能会发生评论在实体之间自动“共享”来自不同表的事件,这可能是不可取的。

【讨论】:

    【解决方案3】:

    使用comment_id 主键和评论的各种属性创建一个comment 表。

    另外,这样创建A_comment

    CREATE TABLE A_comment (
        comment_id PRIMARY KEY REFERENCES comment(comment_id),
        A_id REFERENCES A(A_id)
    )
    

    对 B、C 和 D 执行同样的操作。这样可以确保 comment 和所有其他表之间的引用完整性,如果将 ID 直接存储到 A、B、C 和 D 到 comment 中,则无法做到这一点.

    A_comment.comment_id声明为主键可确保评论只能属于A中的一个条目。它不会阻止评论属于A中的一个条目和B中的一个条目,但只有这么多你可以用外键实现;这将需要数据库级别的约束,我知道没有数据库支持。

    这种设计也不会阻止孤立的 cmets,但我想不出任何方法可以在 SQL 中阻止这种情况,当然,除了做你想避免的事情:创建多个注释表。

    【讨论】:

      【解决方案4】:

      您可以有一个 cmets 表,并且在该表中有一列包含一个值,用于区分注释属于哪个表 - 即,该列中的 1 表示它是表 A 的注释,2 表示表 B,等等在。如果您不想在 cmets 表中包含“幻数”,您可以使用另一个只有两列的表:一列包含数字,另一列详细说明数字代表哪个表。

      【讨论】:

        【解决方案5】:

        你不需要一个单独的评论表,一个就足够了。每条评论都有一个唯一的 ID,因此您不必担心冲突。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-09-08
          • 1970-01-01
          • 2014-10-27
          • 1970-01-01
          • 2014-02-22
          • 1970-01-01
          相关资源
          最近更新 更多