【问题标题】:DB Design: Favor Abstraction or Foreign-Key Constraints?数据库设计:偏爱抽象还是外键约束?
【发布时间】:2009-06-28 18:53:52
【问题描述】:

假设我们有这种情况:

Artist ==< Album ==< Track
//ie, One Artist can have many albums, and one album can have many tracks

在这种情况下,所有 3 个实体都具有基本相同的字段:

  • 身份证
  • 姓名
  • 与对应的孩子(艺术家到专辑和专辑到曲目)的一对多关系的外国人

所提供解决方案的典型解决方案是三个表,在一对多关系字段中具有相同的字段(ArtistID、AlbumID 等)和外键约束。

但是,在这种情况下,我们可以合并一种继承形式来避免相同字段的重复吗?我在说类似的东西:

Table: EntityType(EntityTypeID, EntityName)
       This table would hold 3 entities (1. Artist, 2. Album, 3. Track)

Table: Entities(EntityID, Name, RelField, EntityTypeID)
       This table will hold the name of the entity (like the name of 
       an artist for example), the one-many field (foreign-key
       of EntityID) and EntityTypeID holding 1 for Artist, 2 for Album 
       and so on. 

您对上述设计有何看法?在这个 DB 场景中加入“OOP 概念”是否有意义?

最后,您更喜欢第一个场景的外键约束还是更通用的(例如,存在将艺术家与 Track 链接的风险,因为没有检查输入器外键值真的是专辑)的做法吗?

..btw,想想看,我想你实际上可以检查一个艺术家的 RelField 的输入值是否对应一个专辑,也许有触发器?

【问题讨论】:

  • 您的专辑中没有多位艺术家吗?您的曲目中没有多个艺术家吗?您也不是在录制诸如演奏音乐的乐队(管弦乐队)、独奏家、指挥家、作曲家、编曲家等。嗯,这只是一个问题,但要小心过度简化。

标签: language-agnostic database-design oop entity-relationship


【解决方案1】:

我最近看到这种抽象的想法被一致地实现了,应用程序及其数据库变成了一个需要维护和排除故障的怪​​物。我会远离这种技术。越简单越好,这是我的口头禅。

【讨论】:

    【解决方案2】:

    在各个实体上不可避免地积累的额外字段几乎不可能像义务那样有效。如果不以相当接近的方式反映现实,将一无所获。

    我认为您甚至不会在常规 OO 设计中将这些实体混为一谈。

    这让我(但只是稍微)想起了我曾经看到的一次尝试,即在一个表(名为“实体”)中实现所有内容,另一个表(名为“属性”)和它们之间的连接表。

    【讨论】:

    • 这种抽象的终极方法是 EAV 模型(实体、属性、值),其中绝对可以将所有内容都塞进一张只有三列的表中。无论主题如何变化,架构都不会改变。这是一场噩梦。
    • 这可以走得更远。我们正在维护一个 250K+ LOC 代码库,该代码库对整个模型使用字典的等价物 - 所有模型实例基本上都是 Dictionary (从 web 服务接口开始,通过域对象到附加到 UI 控件的标签)
    【解决方案3】:

    通过将所有三个组合在一起,您的查询的可读性会降低(除非您随后将这三个类别分解为视图),并且会使搜索和索引变得更加困难。

    另外,在某些时候,您会希望将属性添加到一个类别,而不是其他类别的属性。将这三者结合在一起,你就没有改变的余地,而不会破坏你的系统。

    别太聪明了,你把自己绊倒了。

    【讨论】:

      【解决方案4】:

      我可以看到以您的 OOP 方式执行此操作的唯一优势是将来是否添加了其他元素类型(即,除了艺术家、专辑和曲目之外)。在这种情况下,您不需要更改架构。

      但是,我倾向于选择非 OOP 方式并在这种情况下更改架构。您在使用 OOP 解决方案时遇到的一些问题是:

      • 如果要添加艺术家的生日怎么办?
      • 如果您想存储专辑和曲目的时长怎么办?
      • 如果要存储轨道类型怎么办?

      基本上,如果您想存储仅针对一种或两种元素类型的特定内容怎么办?

      【讨论】:

        【解决方案5】:

        如果您对这类事情感兴趣,请查看PostgreSQL 中的表继承。

        create table Artist (id integer not null primary key, name varchar(50));
        create table Album (parent integer foreign key (id) references Artist) inherits (Artist);
        create table Track (parent integer foreign key (id) references Album) inherits (Artist);
        

        【讨论】:

          【解决方案6】:

          我同意 le dorfier 的观点,您可能会从基本实体(ID、名称)的概念中得到一些重用,但除此之外,艺术家、专辑和曲目的概念会有所不同。

          一个更现实的模型可能必须处理多个艺术家可能为一张专辑的单首曲目做出贡献的事实......

          【讨论】:

            猜你喜欢
            • 2020-04-04
            • 1970-01-01
            • 1970-01-01
            • 2015-12-14
            • 2021-11-03
            • 1970-01-01
            • 2015-03-31
            • 1970-01-01
            • 2013-12-17
            相关资源
            最近更新 更多