需要为记录分配多个属性 - 我应该选择一个表还是多个表?

时间:2009-12-18 16:14:29

标签: sql cakephp model-view-controller database-design

我使用MVC模式来表示包含许多音乐专辑记录的表格。每张音乐专辑都有属性(流派,艺术家,收视率等)。每个属性可以有多个值(例如,一个专辑的类型可以是“pop”和“latin”)。我想使用表格来表示这些属性值。

因此,我可以想到两种基本方法。我想知道哪种方法更好?

  1. 为每个属性设置单独的表格(例如GENREARTIST)。每个表中的列将为album_id和attr_value。

  2. 只有一张表ATTRIBUTES,除了album_id和值之外,还会包含属性名称(“genre”,“artist”,...)。

  3. 通常我会选择方法1(关系数据库和所有这些),但如果我选择方法2,我的想法是,当我想添加新属性时,我不需要创建新模型,控制器和观点。

    有什么意见吗?

5 个答案:

答案 0 :(得分:2)

这不是一个MVC问题,而是一个规范化问题。

有一个规范数据库和建立实体(表)的过程。两种典型形式是第3范式或Boyce-Codd范式。搜索任何一个都应提供充足的信息。现在说除了标准规范化之外还有一些其他设计可以使用。这一切都取决于您希望如何平衡错误(更新/插入)和性能。许多人一直在倡导非关系型设计(nosql,couchdb和那些认为今天不需要因空列引起的腐败问题的人)。然后就是现实,序列化阵列开辟了混合设计的可能性。你好像更多地讨论EAV(实体属性值)和附加表。 EAV的设计速度较慢,但​​在输入单元不会提前知道时非常有用。所以对于EAV,如果我有一个艺术家,并且我想添加一个“列”家乡,我不必创建一个新的列表,只是属性表中的一个新条目。 EAV也非常难以验证和输入。

在我的产品中,我发挥它的安全性和关系(Boyce-Codd形式)。是的,它意味着更多的模型和更多的关系,但它值得花费几个小时。除了像标记的Cakephp这样的MVC框架之外,制作模型也不容易。每次我使用EAV我都希望我只是花费额外的时间来计划更多。

答案 1 :(得分:1)

选项3:对于明显且使用最广泛的属性,使用专用表,并为用户定义的属性设置另一个通用表(例如“Annoys前妻多少”)

静态表应该有一组非常静态的属性。

答案 2 :(得分:0)

每当有能力时 - 我使用一个表来表示一个'真实的东西',当这不够时,例如当你必须关联两个不同的想法/对象/事物时,我会使用多个表。

话虽如此,我们都同意使用您的#1想法 - 但现在您希望能够添加新属性。这通常使用'meta'表来处理最简单 - 一个表抽象对象及其属性的实际关系 - 给你你想要的东西 - 动态属性。

看起来像这样

=======================
Table Name: Albums
----------------AlbumID
----------------GenreID --> foriegn key --> Genre in Genre Table
----------------ArtistID --> foriegn key --> Artist in Artist Table
----------------Name
----------------Etc (attributes that you know you will need)
=======================
Table Name: AlbumMeta
----------------AlbumID
----------------Key
----------------Value
=======================

现在 - 您的相册可以具有具体属性(即:所有相册都具有的属性),如果出现新的商家规则,例如仅适用于独立专辑 - 您有一个指向新合作伙伴网站“indiealbums.com”的链接 - 您可以为独立音乐类型中的每张专辑创建一个AlbumMeta条目。

答案 3 :(得分:0)

我会将专辑和流派视为两个截然不同的模特。然后,除了映射它们之间关系的另一个表之外,您还可以为每个属性/模型创建表。数据库结构如下所示:

=====
Table: Albums
-- id
-- name
-- artist

====
Table: Genres
-- id
-- name

====
Table: Album_Genres
-- id
-- album_id
-- genre_id

只需将所有相册和流派添加到相关表格中,然后声明相册属于特定类型,即可在Album_Genres表格中创建新行。如果您将来需要添加/删除任何属性,就像创建/删除几个表一样简单。

答案 4 :(得分:0)

您应该使用第三范式

执行此操作

在CakePHP中,您正在寻找的关系和必填字段是..

<?php
    class Album etends AppModel
    {
        public $name = "Album";
        public $hasAndBelongsToMany = array( 'Artist', 'Genre' );
    }
?>
<?php
    class Artist extends AppModel
    {
        public $name = "Artist";
        public $hasAndBelongsToMany = array( 'Album' );
    }
?>
<?php
    class Genre extends AppModel
    {
        public $name = "Genre";
        public $hasAndBelongsToMany = array( 'Album' );
    }
?>

// fields for the tables with their table names
// only the required ones for the relationships rest is up to you
artists
    --id

albums
    --id

genres
    --id

albums_artists
    --id
    --album_id
    --artist_id

albums_genres
    --id
    --album_id
    --genre_id

这意味着最初输入信息的工作量更多。您必须将类型和艺术家的条目视为数据库中的单独操作。如果您决定将艺术家视为完整的“乐队”或单独的表演者,您将能够使用此设置,因为专辑可以与任意一组艺术家相关联。