问题描述
假设我正在建立一个包含群组和房间的聊天。我需要为它创建关系数据库方案。
- 每组可以有多个房间。
- 并且每组总是恰好有 1 个主房间(这也是与其他房间相同的房间)
- 房间已经预建(无论是否为主房间)结构且无法复制。像它的外键,或描述、通知设置等。
因此,由于它是一对多关系,因此以下数据库架构可以表示此模型:
,-----------------.
|Group |
|-----------------|
|*id: pk |
|*name: string |
|*main_room_id: fk|
`-----------------'
↑ ᗐ
ᗑ ↓,-------------.
|Room |
|-------------|
|*id: |
|*name: string|
|*notif: bool |
|*group_id: fk|
`-------------'
但我想在这个方案中避免循环引用。我可以通过在一个房间里有一个布尔字段来说明这是一个主房间:
,-------------.
|Group |
|-------------|
|*id: pk |
|*name: string|
`-------------'
↑
ᗑ,----------------.
|Room |
|----------------|
|*id: |
|*name: string |
|*notif: bool |
|*group_id: fk |
|*is_main: bool |
`----------------'
但是在使用这个方案时数据库没有被规范化。主房间 is_main
布尔字段取决于其他房间 is_main
字段。此外,应该创建更复杂的约束来支持数据一致性。
针对此问题的适当数据库架构是什么?
解决方法
-- Group GRP exists.
--
group {GRP}
PK {GRP}
-- Room ROM exists.
--
room {ROM}
PK {ROM}
- 每个房间属于最多一个组;
每组可能拥有多个房间。
-- Room ROM is owned by group GRP.
--
room_group {ROM,GRP}
PK {ROM}
SK {ROM,GRP}
FK1 {ROM} REFERENCES room {ROM}
FK2 {GRP} REFERENCES group {GRP}
-
每组最多有一个主房间;
每个主要房间属于一个组。 -
如果一个房间是一个组的主房间,
那么那个房间必须属于那个组。
-- Room ROM is main room for group GRP.
--
main_room {GRP,ROM}
PK {GRP}
AK {ROM}
FK {ROM,GRP} REFERENCES
room_group {ROM,GRP}
注意事项:
请注意,模型中不强制有主房间,请使用应用程序级别来强制执行。
All attributes (columns) NOT NULL
PK = Primary Key
AK = Alternate Key (Unique)
SK = Proper Superkey (Unique)
FK = Foreign Key
,
我不认为这是一种多对一的关系。假设我理解正确,在我们的架构中,每个组都可以与多个房间相关联,并且每个房间也可以与一个或多个组相关联,因此这意味着这是一种多对多关系。
例如,假设您可以在架构中拥有这些关联:
Group Room
group_1 room_1
group_1 room_2
group_2 room_1
group_2 room_2
最好创建一个新实体来保存房间和组实体之间的关系。在这个新实体上,您可以有一个布尔字段来指示哪个关联是 main
。