【问题标题】:Database design dilemma on connecting users with messages将用户与消息连接起来的数据库设计困境
【发布时间】:2015-02-16 09:28:54
【问题描述】:

这是我想出的,但我不确定其中哪一个是“最好的”。也许还有另一种更好的我可能不知道的。请记住,我的应用中同时包含收件箱和发件箱,并且由发件人或收件人删除的邮件仍应对其他相关用户可见,除非他们自己删除。

选项 1 - 简单的多对多:
表:
用户 - 只是用户字段
消息 - 只是消息字段
User_Message - 包含 2 个外键:user_id 和 message_id

示例:当用户发送消息时,消息表中添加了 ONE 消息行,而 User_Message 中添加了 2 行消息,显然将发送者和接收者与添加的消息联系起来。
现在,这可能会有点问题假设我只想获取收件箱消息,因为 ManyToMany 会获取所有这些消息,所以我想出了选项 2。

选项 2 - OneToMany:
表:
用户 - 只是用户字段
MessageReceived - user_id 的消息字段和外键
MessageSent - user_id 的消息字段和外键

示例:当用户发送消息时,该消息将添加到接收表和已发送表中,但 user_id 不同。当然,发件人 ID 将在发送表中,收件人 ID 在接收表中。
现在,当我只想获取收件箱消息时,我正在从 MessageReceived 表中获取消息,并且在删除例如收件箱 (MessageReceived) 消息时,它的副本仍然保留在 MessageSent 中并且可供发件人使用,所以一切都很好,但是我觉得就像这个有一些“不酷”的地方,因为我基本上在两个表中都保留了几乎相同的数据。

请让我知道您对此有何看法,如果有更好的方法,我也在倾听。感谢您的宝贵时间。

编辑:
MadbreaksTab Alleman 都提供了非常好的且有些相似的解决方案,因此非常感谢。我将使用 Madbreaks 之一,只是因为我更喜欢删除连接表中的关系而不是保留“已删除”列,但这只是我的口味。不过,感谢您的时间和回答。

【问题讨论】:

  • 一封邮件可以有多个发件人吗?
  • 为什么要添加两行user_message?有 3 列,sender_id、receiver_id、message_id。您还怎么知道发件人和收件人是谁?
  • 不,用户是发件人,仅此而已。
  • 一对多怎么样。 Messages 有两个 FK 指向 User 表。 FK1 ReceivingUserId,FK2 SendingUserId
  • Madbreaks,是的,你是对的。这是有道理的,但我有一个关于删除它们的问题。当收件人删除一条消息时,它必须为发件人留在那里,那么除了在其中一侧设置 NULL 之外,还有其他方法可以实现吗?

标签: mysql database database-design foreign-keys relational-database


【解决方案1】:

您不需要在 user_messages 中为每条消息添加 2 行 - 该表中有 3 列:sender_idrecipient_idmessage_id

编辑

您在下面的问题中描述的删除场景改变了事情。您现在可能有两个 1 对 n 关系,而不是 n 对 n 方法:

  1. 发件人与其多条已发送消息的关系
  2. 收件人与其收到的许多消息之间的关系

我可能会让消息表有一个发件人 ID 外键。然后我会有一个 message_recipients 表,将用户(收件人)ID 映射到消息 ID。

现在,如果发件人可以删除邮件,但收件人应该仍然可以访问它(并且知道发件人是谁),那么您将需要四个表:

  1. 用户
  2. 消息
  3. message_sender (1-to-1 map) -- 删除已发送消息的发件人从她那里删除
  4. message_recipients (1-to-n map) -- 删除收到的邮件的收件人从此处删除

从您的问题中不清楚这是否是一项要求,我只是为了完整性而添加它。您可能需要触发器或后续查询来确定用户和消息表之间是否/何时没有剩余关系,并在那时(可能)删除消息本身。

【讨论】:

  • 正如我在评论中所说的,就在几分钟前。这是最有意义的,但删除呢?如果收件人删除了邮件,它必须为发件人留在那里,所以我必须在收件人 ID 中设置 NULL,但是我应该如何检索收件人姓名呢?
  • 你没有在你的问题中提到这个删除要求。
  • 那是因为它想出了你的解决方案,所以我想知道如何处理。
  • 我更新了我的答案。最好更新您的问题以澄清其中一些问题。
  • 感谢您的解释,我也会尽快更新我的问题。
【解决方案2】:

这就是我要做的(我假设一条消息只能有一个发件人,但有多个收件人)

  • UserTable - 包含 UserID 和其他信息
  • MessageTable - 有 MessageID、SenderID(FK 到 UserTable.UserID)和其他信息
  • MessageRecipientsTable - 具有 MessageID、RecipientID(FK 到 UserTable.UserID)以及可能的其他信息,例如何时/是否收到等。

如果您希望收件人能够删除邮件并仍将其显示给发件人(和其他收件人),那么您可以将“已删除”列添加到 MessageRecipientsTable。您永远不会真正从消息表中删除一行,但在填充收件人收件箱时,您会过滤掉“已删除”为真的行。

【讨论】:

  • 这也是一个很好的解决方案。如果你不介意的话,只是几个小问题。 1. 与我的选项 2 相比,这是性能提升吗? (问这个是因为插入的行数相同)。 2.如果发件人想从他的发件箱中删除邮件,我想我必须在 MessageTable 中删除一列?
  • 嗯,它肯定比你的选项 2 更规范化,所以它会让你的数据库更小,但你是否看到性能差异我不知道。是的,如果您希望发件人能够从他的发件箱中删除而不从收件人的收件箱中删除,那么您将使用 Message 表中的 Deleted 列。
  • 感谢您的回答,我会在大约 3-4 小时后在家时更新我的​​问题并接受其中一个答案。
猜你喜欢
  • 1970-01-01
  • 2021-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-06
  • 2012-05-15
  • 1970-01-01
相关资源
最近更新 更多