如何构建可与不同表关系的通用项?

时间:2015-03-12 07:49:32

标签: sql activerecord database-design foreign-keys relationship

在我的示例中,我有一个watch,表示用户想要通知其他商品上的活动,例如grouporganization

我认为有两种方法可以做到这一点:

  1. 拥有groupwatch资源,其中包含groupwatch表,idusergroup(FK到group组资源,表);和orgwatch资源,orgwatch表,iduserorganization(org FK到organization资源和表格)< / LI>
  2. 拥有watch表格的通用watch资源,idusertypetypeidtypegrouporganization中的一个,typeid是被观看的grouporganization的ID。
  3. 由于它们都是手表,因此有两个不同的表和资源来观看2个不同的对象似乎是浪费。如果我开始观看4种,5种,6种,20种,50种不同类型的资源,情况会变得更糟。

    另一方面,如果我只有一个通用typeid,则外键关系似乎不可能,这意味着我的数据库(如果是关系)和我的框架(activerecord或其他任何东西)无法正确执行它。 / p>

    如何最好地为表格中的每条记录实现这种“与不同类型的记录/表格的关联”?

    更新:

    这是我做这件事的唯一选择:

    • 为每个watch类型分隔表/资源,这使数据库能够强制执行关系完整性并进行连接
    • 所有watches的单一表格,但我必须强制执行关系完整性并在应用级别进行加入?

1 个答案:

答案 0 :(得分:1)

如果每六个月添加一种新类型的资源,您可能希望以添加新资源涉及更改数据定义的方式定义表。如果每周添加一个新资源类型,则可能需要在添加新类型时使数据定义保持不变。这两种选择都有不利之处。

如果您确实选择以表格结构中可见类型的方式定义表格,则有两种模式通常与类型/子类型(也称为类/子类)情境一起使用。

一种模式被称为&#34;单表继承&#34;。将所有类型的数据放在一个表中,并在不适用的地方留下一些NULL。

另一种模式被称为&#34;类表继承&#34;。为超类定义一个表,其中包含所有类型共有的所有数据。然后为每个子类型(子类)定义表以包含特定于类的数据。使子类型表的主键与超类型表中的主键重复,并将其声明为引用超类型表的主键的外键。在插入时,它将在应用程序中更新,以便在子类型表中复制超类型表中的主键值。

我喜欢Fowlers&#39;治疗这两种模式。

http://martinfowler.com/eaaCatalog/classTableInheritance.html http://www.martinfowler.com/eaaCatalog/singleTableInheritance.html

共享主键的问题有一些有益效果。

首先,它强制执行ISa关系的一对一性质。 其次,通过仅加入子类型表,可以很容易地找出给定条目是否属于所需的子类型。你真的不需要额外的类型字段。 第三,它加速了连接,因为在声明主键时会生成索引。

如果您想要一个可以在不更改数据定义的情况下适应新属性的结构,您可以查看E-A-V设计。但要小心。有时,这会导致数据几乎无法使用,因为逻辑结构非常模糊。出于这个原因,我通常认为E-A-V是一种反模式,尽管有些人真的很喜欢他们从中得到的结果。