【问题标题】:Advice on design relations between tables表间关系设计建议
【发布时间】:2017-03-15 21:52:38
【问题描述】:

我有关于音乐专辑的信息,我想在 RDBMS 表中组织它们之间的关系。我有每张专辑的以下信息:艺术家、专辑名称、年份、标签、流派、风格、评级。到目前为止,我认为要制作 4 个表格 - 艺术家、专辑(名称、年份、标签、评级)、流派 1 和流派 2(每种流派都有其风格)。上图如下:

但还不知道如何在相册和其他三个表之间建立连接?即,当我运行查询 select name from artists 时,我想收到一张带有相应艺术家和流派风格的专辑。

在这种情况下我应该如何建立表之间的关系?

【问题讨论】:

    标签: sql database-design foreign-keys relational-database foreign-key-relationship


    【解决方案1】:

    您需要阅读关系数据库表和查询​​的介绍。

    您所说的表之间的“关系”[原文如此]是 FK(外键)。 FK 表示表中列列表的值显示为表中其他一些列列表的值,这些列在此处形成 PK(主键)或 UNIQUE 集。您无需声明或使用 FK 即可查询。与所有约束一样,包括 PK 和 UNIQUE,它们用于 DBMS 排除错误的数据库状态。

    一个(基础或查询结果)代表一个(业务/应用)关系(船)/关联。一个表包含从关联的谓词(语句模板)生成一些真正的proposition(语句)的行。基表的谓词由 DBA 给出。查询结果表的谓词来自用户查询表达式中的基表、关系运算符和逻辑运算符。即 JOIN 的谓词是其表的谓词的 AND;联合手术室;除了 AND NOT;条件的 ON 和 WHERE 以及带有 JOIN 谓词的条件; etc.

    -- artist A has name N
    Artist(A, N)
    -- album A has name N and ...
    Album(A, N, ...)
    -- genre G has name N
    Genre(G, N)
    -- artist A authored album A2
    ArtistAlbum(A, A2)
    -- album A is of genre G
    AlbumGenre(A, G)
    
    SELECT DISTINCT ...
    FROM
        --     album ag.A is of genre ag.G AND genre g.G has name g.N ...
        -- AND ag.G = g.G ...
        AlbumGenre ag JOIN Genre g ON a.G = g.G ...
    

    注意无关紧要一个专辑可以有多少个流派,一个流派可以有多少个专辑,或者一个流派是否可以有多个 id 和/或名称,查询仍然返回行满足那个谓词。 查询或更新不需要约束(包括 FK)。

    请注意,我们可以应用相同的谓词转换以及其他转换来编写约束。 (我对作者和专辑都使用了A,所以我必须在这里举一个重命名的例子。)

    -- for all A & A2, if artist A authored album A2 then artist A has some name
    -- for all A & A2, if artist A authored album A2 then for some N, artist A has name N
    -- for all A & A2, if (A, A2) in ArtistAlbum then for some N, Artist(A, N)
    -- SELECT A FROM ArtistAlbum ⊆ SELECT A FROM Artist
    FOREIGN KEY ArtistAlbum (A) REFERENCES Artist (A)
    
    -- for all A & A2, if artist A authored album A2 then album A2 has some name
    -- for all A & A2, if artist A authored album A2 then for some N, ..., album A2 has name N and ...
    -- for all A & A2, if (A, A2) in ArtistAlbum then for some N, ..., (A2, N, ...) in Album
    -- SELECT A2 FROM ArtistAlbum ⊆ SELECT A AS A2 FROM Album
    FOREIGN KEY ArtistAlbum (A2) REFERENCES Album (A)
    
    -- for all A & G, if album A is of genre G then album A has some name and ...
    -- for all A & G, if album A is of genre G then for some N, ..., album A has name N and ...
    -- for all A & G, if (A, G) in AlbumGenre then for some N, ..., (A, N, ...) in Album
    -- SELECT G FROM AlbumGenre ⊆ SELECT A FROM Album
    FOREIGN KEY AlbumGenre (A) REFERENCES Album (A)
    
    -- for all A & G, if album A is of genre G then genre G has some name
    -- for all A & G, if album A is of genre G then for some N, genre G has name N
    -- for all A & G, if (A, G) in AlbumGenre then for some N, (G, N) in Genre
    -- SELECT G FROM ArtistAlbum ⊆ SELECT G FROM Genre
    FOREIGN KEY AlbumGenre (G) REFERENCES Genre (G)
    

    我们可以只使用 Album2 作为它们的连接,而不是有两个表 Album 和 AlbumGenre 以及它们的 FK,谓词是它们的谓词 album A has name N and ... and album A is of genre GFOREIGN KEY Album2 (G) REFERENCES Genre (G) 的 AND/连接。然后规范化会告诉我们,如果每张专辑有一个流派,那么这是一个好的设计,但否则原版更好。同样,对于 Artist2,将 ArtistAlbum 合并为 Artist(如果艺术家创作了一张专辑,这是合理的)。或者将 ArtistAlbum 和 AlbumGenre 都放入 Album3(如果专辑有一位作者和一种流派,则合理)。但无论如何,查询和更新重要的是谓词,而不是基数或约束。

    因此,您的设计缺少像 ArtistAlbum 和 AlbumGenre 那样的适当谓词/列/表。 (您可能希望与上述其他表格结合使用。)

    PS 你的问题不清楚“流派”、“流派1”和“流派2”。

    【讨论】:

      【解决方案2】:

      底线是您需要外键。您的表当前对于每个名为 id 的表都有一个不同的 id:

      artist.id
      artist.name
      album.id
      album.album
      album.year
      album.label
      album.rating
      genre.id
      genre.name
      genre.id
      genre.name
      

      这里的关键词是“关系”。您需要关联表格。也许你会通过更好地命名你的 id 来设计这个:

      artist.artist_id
      album.album_id
      genre.genre_id
      

      然后在专辑表中,您将为艺术家 ID 和流派 ID 添加列,以便您可以将它们重新加入到艺术家和流派表中

      没有 FK,您将获得笛卡尔积。就这么简单。

      【讨论】:

      • 然后在album 表中,我需要添加一个列artist_idgenre_id 将指向artistgenre 表中的相应行?我想到了两张genre 桌子,因为一张是摇滚的,另一张是爵士的。
      • 我编辑了我的帖子以解决您的第一个问题。关于流派,您在创建 2 个流派表时完全违背了表的目的。爵士是一排有自己的钥匙,摇滚是另一排有自己的钥匙。这与为什么不为每个艺术家或每张专辑建立一个表的概念相同。
      • @VitaliiPlagov &fleetmack PKs/UNIQUEs & FKs 不需要查询。例如,只要连接为 ON 条件,就不会有叉积,即不必涉及 PK/UNIQUE 或 FK,即一列不必必须另一个列的子集,它是 PK/UNIQUE(即 FK),不需要与其 PK/UNIQUE 进行比较。看我的回答。
      猜你喜欢
      • 2017-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-20
      • 1970-01-01
      相关资源
      最近更新 更多