一对多关系中的特征值,哪个表应该保持这个?

时间:2012-07-07 18:42:47

标签: mysql sql

说我有一对多关系,其中有两个表,一个Person表和一个Belonging表。现在,每个人只有一个最喜欢的属性,特定的属性也不属于另一个人。

我的问题是,哪些信息可以更好地保存?在Person表中作为favorite_belonging_id或在Belonging表中作为is_favorite条目?在我看来,第一选择似乎是更好的版本,但我想听听知识渊博的人们对此有何看法。

编辑:一个人有许多物品,但只有一个最喜欢的物品,每个物品只能属于一个人。这是一对多的协会。

7 个答案:

答案 0 :(得分:3)

我很想接受你的第一个建议(favourite_belonging_id表中的Person列),因为可以创建从(person_id, favourite_belonging_id)到{{的外键引用1 {}在(owner_id, belonging_id)表中。

如果要在Belonging表格中创建is_favourite标志的另一条路线,则没有明显的方法可以确保人员最喜欢的归属关系的1:1性质(复合如果某个人拥有多件不属于他们喜爱的物品,则Belonging上的UNIQUE索引会失败。

那就是说,(owner_id, is_favourite)表中的这个信息确实不属于属于,因为它不是真正属于这个人的属性,而是它的属性。 Person。如果您对此感到强烈,可以创建一个Belonging表,其{1}}(或Favourites)索引超过UNIQUE

答案 1 :(得分:2)

对我而言,它不属于人员表,因为它与基础人无关。

如果您只有归属表 - 我也假设其中有person_id,那么这就是您表达归属与人之间关系的地方,也是限定符也应该去的地方。

另一个选择是在中间连接第二个表 - 在这种情况下,最喜欢的标志就在那里。

修改: 我在设计中的偏好是第三个表选项 - 在这里你可以设置一个开始日期和结束日期以及最喜欢的标志 - 这将允许你理论上在某个时间点交换属于另一个人但仍然知道发生了什么

答案 2 :(得分:1)

我看到几乎所有不同的选项都已经在不同的答案中列出,但是我没有评论所有人给我的印象,我认为你应该做什么,我只会自己创建一个答案。 / p>

只是要清楚我是如何理解系统如何运作的:所有用户都可以拥有多件物品,但任何所有物品只能由一个人提供帮助。

在这种情况下,最有意义的是在所有物表中具有可以将所有物绑定到人的user_id。一旦设置了user_id,就没有其他人可以声明它了。

现在,至于“最喜欢的”部分,你可以做几件事。真正最好的方法取决于您计划在其上运行的查询。有些人考虑添加一个JOIN表,但老实说这是一些相当无意义的额外数据;作为用户表可能会有确切的行数,并将其放在一个单独的表中,有很多你不能做的事情(例如,看看有多少人不喜欢) 。同样,JOIN表对于user_belonging关系没有任何意义,因为所有者和可以拥有它的人数之间存在1:1的关系。
所以我相信有两个可行的选择:在所有物表中添加一个字段(/开关)以指示用户的归属是他/她的最爱,或者在用户表中添加一个字段以指示哪个归属是用户的最爱。我个人认为后者具有最大的优点,但根据你运行的查询,它可能对前者更有意义。总的来说,最大的区别在于你是想要预先插入还是后选择处理的东西;例如在后一种情况下,你将不得不运行一个独立的查询来确定用户是否已经有了一个收藏夹(在前一种情况下,这将不是必要的,因为你会在用户表中的字段上放置一个唯一的索引),而在后选择的情况下,您将不得不进行交叉引用,所属的表中所选择的所有物品中的哪一个是用户的最爱。

如果我清楚地解释了自己,或者您还有其他问题,请告诉我。

答案 3 :(得分:1)

以下可能不是最佳选择,因为它提供了一种标记最喜欢的属性的非常规方法。但是,这样做的好处是,你只需要两个没有循环引用的表,每个人都可以保证不超过一个最喜欢的归属。

所以,它是两个表,people(或persons)和belongingspeople表具有以下结构:

person_id INT AUTO_INCREMENT,
other columns as necessary,

PRIMARY KEY (person_id)

belongings表的创建方式如下:

belonging_id INT AUTO_INCREMENT,
person_id    INT NOT NULL,
is_favourite enum ('1'),
other columns as necessary,

PRIMARY KEY (belonging_id),
FOREIGN KEY (person_id) REFERENCING people (person_id),
UNIQUE (person_id, is_favourite)

关键元素是将is_favourite声明为具有单个可能值的可空enum。这样,当您在(person_id, is_favourite)对上声明唯一约束时,您可以拥有尽可能多的具有相同person_id和空(null)is_favourite的行,因为唯一约束忽略至少有一个成员为null的行。而且,您将无法使用person_id创建多个is_favourite = '1',因为 会违反唯一约束。

答案 4 :(得分:1)

都不是。我的建议是添加另一个表person_favourite_belonging,如下所示:

CREATE TABLE person
( person_id INTEGER NOT NULL
--- various other columns about Persons
, PRIMARY KEY (person_id)
) ;

CREATE TABLE belonging
( belonging_id INTEGER NOT NULL 
, person_id INTEGER NOT NULL 
--- various other columns about Belongings
, PRIMARY KEY (belonging_id)
, UNIQUE KEY (person_id, belonging_id)       --- this Unique constraint is needed
, FOREIGN KEY (person_id)
    REFERENCES person (person_id)
) ;

CREATE TABLE person_favourite_belonging
( person_id INTEGER NOT NULL 
, belonging_id INTEGER NOT NULL
, PRIMARY KEY (person_id)
, FOREIGN KEY (person_id, belonging_id)      --- for this Foreign Key constraint
    REFERENCES belonging (person_id, belonging_id)
) ;

这是我首选的方式。有其他选择,都有其优点和缺点。采用这种方法的专业人士是:

  • 外键约束中没有循环路径(因此):
  • 插入,删除或更新“人物”,“物品”或“最喜欢的物品”时,没有鸡和蛋的问题。
  • 所有外键列都可以定义为NOT NULL。
  • 可以在数据库级别强制执行完整性。
  • 如果您的要求发生变化,并且您希望每人拥有2个(或更多)收藏,则只能在收藏夹表格中正确更改约束。

同时检查我在这个问题中的答案(问题几乎相同):In SQL, is it OK for two tables to refer to each other?

答案 5 :(得分:0)

favourite_thing是归属表的FK(如果该表存在,否则它可能是域),但在附加约束中,您可以强制在employees表中的belongs_id是唯一的。

更新:

DROP table belonging;
CREATE table belonging
        ( id INTEGER PRIMARY KEY
        , description varchar
        );

DROP table person;
CREATE table person
        ( id INTEGER PRIMARY KEY
        , description varchar
        , favourite_thing INTEGER REFERENCES belonging (id)
        );

-- Now add the unique constraint
-- NOTE: favourite_thing can still be NULL
ALTER TABLE person
        ADD CONSTRAINT must_be_unique UNIQUE (favourite_thing)
        ;

更新2:如果每个所有物属于仅属于一个人,您可以将所有者字段添加到所有物:

CREATE table belonging
        ( id INTEGER PRIMARY KEY
        , owner_id INTEGER NOT NULL REFERENCES person(id)
        , description varchar
        );

DROP table person CASCADE;
CREATE table person
        ( id INTEGER PRIMARY KEY
        , description varchar
        , favourite_thing INTEGER REFERENCES belonging (id)
        );

ALTER TABLE person
        ADD CONSTRAINT must_be_unique UNIQUE (favourite_thing)
        ;

答案 6 :(得分:-1)

实际上你提出了一对一的关系。 所以你可以: 1.将其保存在Person表中。 2.把它放在Belonging table中。 把它拿在两者里面。 把它放在另外的桌子里。