3

我有三个数据库表:

  • 用户
  • 电子邮件
  • 邀请函

电子邮件通过 user_id 字段链接到用户。

邀请也通过 user_id 字段链接到用户

无需邀请即可创建电子邮件,但每个邀请都必须有电子邮件。

我想链接电子邮件和邀请表,以便可以找到特定邀请的电子邮件。

但是,这会创建一个循环引用,邀请和电子邮件记录都保存同一用户的 id。

这是糟糕的设计吗?如果是这样,我该如何改进它?

我的感觉是使用外键和良好的业务逻辑就可以了。

users
-----
id

emails
------
id
users_id

invitations
-----------
id
users_id
emails_id
4

5 回答 5

2

这不是循环引用

如果电子邮件与邀请具有强完整性关系,并且邀请与电子邮件具有独立的强完整性关系(例如),这将是。

编辑:关于设计

正如 Henk Holterman 指出的那样,问题是您的设计是否已标准化到所需的程度。

模拟表:主键

用户:id
电子邮件:id、users_id
邀请:id、users_id、emails_id

并假设 table_id 字段上的外键并且没有在表上放置其他约束(例如,只有键的一部分是唯一的),那么您已经对以下内容进行了建模:

  • 对于每个用户,可以有多个电子邮件,并且您不能拥有没有相应用户记录的电子邮件
  • 对于每封电子邮件,可以有多个邀请,并且您不能有没有相应电子邮件或用户记录的邀请(注意:根据上述定义,我们无法知道 user_id 是指电子邮件中的条目还是用户中的条目)

现在只有您可以说这些规则是否与您尝试建模的真实世界情况相对应。

查看数据库设计的一种方法是 - 实际上没有错误的数据库设计,您几乎总能找到可以使看起来像错误的数据合理的数据。这就是为什么如果不同时考虑规则(以句子的形式)和表格(ER图,表格和关系的描述),就不可能说设计中是否存在问题(尽管可以根据个人经验给出建议)。

为了说明 - 上面的注释不清楚 user_id 指的是哪个表似乎很容易回答。考虑到您说每个邀请都有一封邮件,常见的答案是它应该引用邮件表中的 user_id 。

否则,可能存在邀请中记录的 user_id 与邮件中记录的 user_id 不同的邀请。

通常,这应该会使标有“规范化您的数据”的红灯在您的脑海中闪烁。但是,这里通常不言而喻的假设是 email_id 决定了 user_id,这可能不是真的(!)。

这取决于您的数据的语义(每个表的谓词) - 例如,如果您尝试模拟可以向一个人发送邀请并接收另一个人的电子邮件回复的情况(例如通过秘书邀请人们并收到直接回复),然后红灯熄灭,一切都很好——这就是真正发生的事情,这就是你在设计中要允许的。

于 2010-04-08T08:17:34.140 回答
1

我认为这里正确的正常形式是让邀请与电子邮件而不是用户具有 FK 关系。我认为这会很好。

在您的描述中,您声明邀请属于用户,但从约束来看,更准确地说邀请属于电子邮件。

另一方面,你是对的,同时给 Invitation 一个 UserId 和一个 EmailId 不会是一个大问题。它也不会带来太多好处。

于 2010-04-08T08:16:31.593 回答
1

每个邀请都必须有一封电子邮件,但可以在没有邀请的情况下创建电子邮件。好的 - 但是可以在没有用户的情况下创建电子邮件吗?

  • 如果邀请必须有电子邮件,并且电子邮件也必须属于某个用户,那么该邀请确实与某个用户相关。在这种情况下,您当前的数据模型是可以的,您不需要添加任何字段 - 您只需通过用户 ID 将邀请加入电子邮件。

  • 如果电子邮件可以在没有用户的情况下存在,那么它们独立于用户和邀请。在这种情况下,您应该在链接到“电子邮件”表的“用户”和“邀请”中都有一个“电子邮件 ID”字段。但是,在这种情况下,您最终可能会遇到这样一种情况:用户有一封电子邮件,而他的邀请有一封单独的(或重复的)电子邮件。

于 2010-04-08T09:42:19.847 回答
1

无需邀请即可创建电子邮件,但每个邀请都必须有电子邮件。

可以有超过 1invitationemail吗?如果不是,那么你的设计已经错了。

我想链接电子邮件和邀请表,以便可以找到特定邀请的电子邮件。但是,这会创建一个循环引用,邀请和电子邮件记录都保存同一用户的 id。

(对我而言)不清楚user_idin是否invitation指的是相同user_id的 in email。如果是这样,那么它是多余的并且是去规范化。删除它,并email用作您的链接表以返回到user_id. 如果您需要它来提高性能等,请在两列之间创建一个unique constraint跨键email.(id, user_id)(已经是唯一的,因为这id是您的主键)和一个外键。这可以在不牺牲数据完整性的情况下为您提供非规范化。

如果它是不同 user_id的,那么您可能需要稍微改进您的命名。类似的东西invited_user_idemail.user_id变成email.sent_by_user_id.

于 2010-04-08T11:24:35.953 回答
1

我认为您对您已经拥有的所有答案都很满意,我只是不会使用复数形式的表名。

这是令人困惑和不必要的。

我同意 user_id 不属于邀请表的观点,但前提是您确实确定要在 user_id 和 email_id 之间建立牢固的联系。

如果是这种情况,那么只需从邀请表中删除 user_id,它是无用的。

于 2011-12-06T02:45:43.573 回答