用于将表与其他 2 个表中的 1 个相关联的数据库设计

Posted

技术标签:

【中文标题】用于将表与其他 2 个表中的 1 个相关联的数据库设计【英文标题】:Database design for relating a table to 1 of 2 other tables 【发布时间】:2014-12-19 02:37:06 【问题描述】:

我有一个包含一些用户和代理的数据库,并想添加一个简单的消息系统。

所以我有以下一组简单的表格:

[users]
- user_id (PK)

[agents]
- agent_id (PK)

[message_threads]
- message_thread_id (PK)

[message]
- message_id (PK)
- message_thread_id (FK messages_threads.message_thread_id)

我没有来自消息和发布消息的个人的关系。

我有点卡住了,因为它可能是用户或代理。我认为这一定是一个常见问题,需要解决一个公认的模式,但我还没有找到这样的讨论。

我知道我有几个选择,但它们都有缺点。

选项 1: 我不喜欢一条消息可以将两个链接到不同的帐户。

[message]
- message_id (PK)
- message_thread_id (FK messages_threads.message_thread_id)
- user_id (FK users.user_id, ALLOW NULL)
- agent_id (FK agents.agent_id, ALLOW NULL)

选项 2: 这使得在 SELECT 的一列中获取所有消息变得很尴尬。

[message_by_user]
- message_id (PK)
- message_thread_id (FK messages_threads.message_thread_id)
- user_id (FK users.user_id)

[message_by_agent]
- message_id (PK)
- message_thread_id (FK messages_threads.message_thread_id)
- agent_id (FK agents.agent_id)

将用户和代理合并到一张表中是我不能做的一件事。这是一成不变的。

【问题讨论】:

【参考方案1】:

听起来用户和代理都是我称之为“人员”的超类的子类。您可以再为人员提供一张桌子,以 person_id 作为 PK。然后,您可以在 users 表中将 user_id 替换为 person_id。同样,将agents 表中的agent_id 替换为person_id。

请注意,在用户和代理这两个子类表中,person_id 具有双重职责。它是它自己的表的PK,也是persons 表的FK。这加强了用户和个人之间以及代理和个人之间的 IS-A 关系的一对一性质。

现在,您所要做的就是在消息和人之间建立关系,嘿,快!消息与用户或代理之间存在关系,视情况而定。

这是一种称为“类表继承”和一种称为“共享主键”的设计模式的实例。您可以通过在 *** 中访问具有相同名称的标签或通过在网络上搜索 Martin Fowler 对该主题的处理来获取有关这些的更多信息。

【讨论】:

可以在How do I map an IS-A relationship into a database?找到关于这个设计的一个很好的讨论

以上是关于用于将表与其他 2 个表中的 1 个相关联的数据库设计的主要内容,如果未能解决你的问题,请参考以下文章

FULL OUTER JOIN 将表与 PostgreSQL 合并

Oracle:将两个表与一个公共列加上第二个表中的一个附加列(最新生效日期)连接以选择其他列

顺序表与链表

Oracle怎样创建关系表与其他的一个表关联

Oracle Join 表与第一个表中的日期范围和第二个表中的日期

将表中的所有行与其他表中的第一个匹配行连接起来[重复]