【问题标题】:Sql one foreign key for different tables不同表的sql一个外键
【发布时间】:2023-03-30 09:38:01
【问题描述】:

首先,我确实意识到有很多关于这个问题的问题,而且我很有可能已经知道其中一个答案,但是在我尝试了其中的几个之后,没有一个对我有用我。

在我的应用程序中,我正在处理用户和客户之间的通信。用户和客户都可以有多个电子邮件地址。此外,用户和客户都可以同时分配到多个对话中。在用户或客户发送电子邮件消息后,系统会收到相关信息并创建一个包含消息基本信息的 ConversationMessage 和包含特定数据(主题、FROM、TO 等)的 EmailMessage。

现在,FROM 和 TO 字段只是带有电子邮件地址的 varchar 字段。我想将其更改为 FROM 和 TO 字段是外键。我正计划创建一个 EmailAddresses 表,该表将存储有关地址的基本信息以及 UserEmailAddresses 和 ContactPersonEmailAddresses 表以及有关地址的特定信息(如主机、端口等),但我意识到 EmailAddresses 表将只包含一个 Id。这是一个好方法吗?我错过了什么吗?

这类问题有更好的解决方案吗?

感谢您的帮助!

【问题讨论】:

  • 大概 EmailAddresses 表除了 ID 之外还有电子邮件地址,对吧?这种方法根本没有错。但是你需要有那种水平的标准化吗?您是否预计会有多个用户拥有相同的电子邮件地址?有时这是有道理的,但听起来很可能过度标准化。
  • 是的,一个电子邮件表被 EmailMessages 中的 2 个外键约束引用(用于 FROM 和 TO)。而且还有一个 PersonEmailCrossRef 表,它保存了 Person 和 Emails 之间的关系,您可以添加约束以强制只有 1 个人拥有电子邮件地址等。至于将端口、主机等放在哪里,我不确定您要跟踪的确切内容但是,如果您想要所有电子邮件详细信息,那么它将在 EmailMessages 或其自己的表中,因为端口、主机等可能不会经常更改,但它们确实会发生变化。此外,它们很可能与域相关而不是电子邮件
  • 存储端口等也可能是多余的,您可能只想将标头存储在 EmailMessages 表中,这将占用更多空间,但由于负载平衡等正在发挥作用,因此会占用更多空间。至于客户电子邮件地址,您为什么要将其保留为空。客户是一个人,所以如果您的客户有一个人的外键,而人有一个 PersonEmailCrossRef 的键,那么通过遍历这些键,您的客户也可以拥有电子邮件地址......这就是为什么我建议一个人是person 是一个人(用户、客户、联系人)等都是人
  • 在基类(表)Person 到 Email 到 Email Message 等上建立关系。从继承的类 User/Customer 中过度复杂化并使事情变得多余。
  • 哦,我知道了,您想存储身份验证数据以便能够访问 IMAP 电子邮件,然后我会将其存储在电子邮件表或域表中,用于端口和服务器地址以及密码电子邮件表(当然是加密的 :))

标签: sql sql-server database foreign-keys


【解决方案1】:

设计存在许多问题,但让我们将讨论限制在电子邮件地址中。您将地址存储在两个表中。不出所料,这会导致问题。

电子邮件地址是一个实体。将它们存储在一个表中。在任何需要单个地址的地方,将 FK 放置到那里的一个地址表中。如果需要或可能需要多个地址,请在此处放置一个交集表。

create table EmailAddresses(
  ID     int   auto_generating primary key,
  Addr   varchar not null unique,
  Active bool
);

诸如登录、端口等字段真的是电子邮件地址的属性吗?如果你愿意的话,也许你可以澄清一下。

那么表 UserEmailAddresses 和 ContactEmailAddresses 将是交集表,看起来像这样:

create table [User|Contact]EmailAddresses(
  UserID   int  not null references [Users|Contacts]( ID )],
  AddrID   int  not null references EmailAddresses( ID )
);

由于电子邮件消息只能有一个“发件人”值,因此它会像现在一样位于 EmailMessages 行中,但它现在可以是一个地址表的 FK。一条消息可能有一个或多个“To”值,因此也可以作为交集表实现:

create table EmailTo(
  EmailID  int  not null references EmailMessages( ID )],
  ToID     int  not null references EmailAddresses( ID ),
  ToType   enum( To, CC, BCC )
);

可能还有其他要求需要对上述任何或所有表格进行一些限制,但这取决于您的使用情况。例如,即使电子邮件应用程序允许同一地址在“发件人”列表中多次存在,您也可能希望捕获并限制此类事件。这将通过 (EmailID, ToID) 上的唯一约束来实现

可能的扩展是添加本身包含一组地址的电子邮件列表。这将需要拆分 EmailAddresses 表,但由于现在所有地址都位于一个表中,因此重新设计肯定比将它们位于两个表中更容易。

【讨论】:

  • 感谢您的回复。登录、端口等是用于连接到用户的电子邮件 (IMAP) 服务器的字段。这种方式系统可以访问(当用户登录时)传入消息等。我已经通过删除单独的电子邮件表并创建一个引用人员表的表解决了这个问题。感谢您提供多个 To 字段的想法,但我并没有真正考虑过,这是一个非常好的想法。
猜你喜欢
  • 2018-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-19
  • 1970-01-01
  • 2017-01-16
  • 2023-03-17
  • 2018-06-13
相关资源
最近更新 更多