我有一个情况:
基本上,有两个实体(用户和事件),但关系并不简单。我的意思是,创建活动的用户可能与参加活动的人不一样。用户可能只是参与者,但不是创建者。
情况类似于this。
我意识到这些关系不只是多对多。
例如,我可以创建两个具有两个关系的表(循环关系)。为了打破这个圈子,我需要允许创建一个没有事件的用户(参与者),暂时为其分配NULL,或者创建一个指示该用户是否也是创建者的列(布尔值)。
但是我通过创建第三个表来解决它:
第三个表存储事件及其参与者。
我还找到了解决这个问题的另一种方法。它涉及4个表:
这些关系看起来像这样:
哪种解决方案更好?
我喜欢有两张桌子的那张,但我只需要深入挖掘并找到合适的。
我坚持使用三个表的解决方案,因为事件总是由一个用户创建。 EventMember
表解决了User
和Event
之间的n:m关系,是必要的。
介绍第四张表Creator
真的没有意义,因为它只增加了一个JOIN
来获得一个事件的创建者。
规则如最初所述
创建活动的用户可能与参加活动的用户不同。用户可能只是参与者,但不是创建者。
这似乎表明,对于每个事件,给定用户可以是参与者或创建者,但不是两者。
但是,在评论中,OP后来表示:
用户可以是参与者,创建者或两者。
以下代码基于先前的假设(正如我在评论中明确指出的那样);适应后来澄清的唯一调整是放弃CHECK
约束:
-- Rule: for each event, a given user may be an attendee or a creator but not both.
-- Rule: each event has zero or one creator.
-- Rule: each event has zero, one or many attendees.
-- General Rule: a table models an entity or a relationship but never both.
CREATE TABLE Users
(
user_name VARCHAR(20) NOT NULL,
UNIQUE (user_name)
);
CREATE TABLE Events
(
event_name VARCHAR(30) NOT NULL,
UNIQUE (event_name)
);
CREATE TABLE EventCreators
(
event_name VARCHAR(30) NOT NULL,
creator_user_name VARCHAR(20) NOT NULL,
UNIQUE (event_name),
UNIQUE (event_name, creator_user_name),
FOREIGN KEY (event_name)
REFERENCES Events (event_name),
FOREIGN KEY (creator_user_name)
REFERENCES Users (user_name)
);
CREATE TABLE EventAttendees
(
event_name VARCHAR(30) NOT NULL,
creator_user_name VARCHAR(20) NOT NULL,
attendee_user_name VARCHAR(20) NOT NULL,
UNIQUE (event_name, attendee_user_name),
FOREIGN KEY (event_name, creator_user_name)
REFERENCES EventCreators (event_name, creator_user_name),
FOREIGN KEY (attendee_user_name)
REFERENCES Users (user_name),
CHECK (creator_user_name <> attendee_user_name)
);
我这样做:
3张桌子(就像多对多)
表1:用户
表2:Users_Events
表3:事件
表2将包含: - 表1中的FK
因此,如果我们说Bob今天创建了一个活动,并且明天将Sarah和John添加为与会者,那么您将拥有(第一列是表1和2的PK):
表1 1 - Bob 2 - Sarah 3 - John
表2 1 - A - 组织者 - 05.01.2012 2 - A - 参加者 - 06.01.2012 3 - A - 参加者 - 06.01.2012
表3 A - 超级新事件
如果你想让Bob参加会议,那么必须在表2中创建一个新记录1 - A - 参加者 - 06.01.2012
然后,如果您需要参与活动A,则需要加入表1 2和3并在table_2上过滤“Attendee”
为了避免在组织者参加的情况下双重输入,您可以通过这种方式获得表2:
表2将包含: - 表1中的FK - 表3中的FK - 参加者(布尔) - 组织者(布尔)
这更加灵活,例如,如果您以后需要跟踪谁将在会议中发表演讲,您可以在不破坏表格的情况下引入新的列播放器。如果您预见到许多角色,那么这将无法扩展