衍生概念——数据库设计注意事项

发布于 2024-11-09 05:59:03 字数 1292 浏览 4 评论 0原文

我有一个主要概念 - 邮件消息和两个派生概念:

  • 模板生成的电子邮件
  • 自由格式电子邮件

我正在考虑创建三个表来保存数据,我需要您对此事的意见(如果是的话)不好,如果好的话,如何改进等等):


MailMessages

  • Id [int] identity(自动增量) PK
  • ToAddress [varchar(300)]
  • IsTemplateBased [bit ]
  • TemplateId [int] 可为 null FK
  • MailBodyId [int] 可为 null FK (TemplateId 必须为 null 并且MailBodyId 必须为非空,反之亦然)
  • StatusId [tinyint] FK

MailParams

  • MailMessageId [int] PFK
  • ParamNumber [tinyint]
  • 值 [nvarchar(4000) ]

MailBody

  • MailMessageId [int] PFK
  • FromUsername [varchar(30)]
  • FromDomainId [tinyint] FK
  • PlainTextContent [nvarchar(max)]
  • HtmlContent [nvarchar(max)] nullable

这里有一些解释:

  • 我希望设计尽可能规范化
  • IsTemplateBased 位(布尔)列可以省略,邮件消息的性质可以从 TemplateId 和/或 MailBodyId 推断出来(即:如果 TemplateId 不为空,那么它是基于模板的),但我认为这种反规范化(?)可能对性能有用
  • 拥有两列(FromUsername 和 FromDomainId)背后的原因是强制执行电子邮件健全性规则 - 我不认为拥有单个列(FromAddress)是合适的

说了所有这些,亲爱的读者,您的意见是什么?

I have a main concept - Mail message and two derived concepts :

  • template-generated emails
  • free-form emails

I am thinking of creating three tables to hold the data and I need your opinions on this matter (if it's bad, if it's good, how can it be improved and so on) :


MailMessages

  • Id [int] identity (autoincrement) PK
  • ToAddress [varchar(300)]
  • IsTemplateBased [bit]
  • TemplateId [int] nullable FK
  • MailBodyId [int] nullable FK (TemplateId must be null and MailBodyId must be non-null or vice-versa)
  • StatusId [tinyint] FK

MailParams

  • MailMessageId [int] PFK
  • ParamNumber [tinyint]
  • Value [nvarchar(4000)]

MailBody

  • MailMessageId [int] PFK
  • FromUsername [varchar(30)]
  • FromDomainId [tinyint] FK
  • PlainTextContent [nvarchar(max)]
  • HtmlContent [nvarchar(max)] nullable

A few explanations are in order here :

  • I would like a design as normalized as possible
  • The IsTemplateBased bit (boolean) column can be omitted and the nature of the mail message can be inferred from TemplateId and/or MailBodyId (i.e.: if TemplateId is not null then it's template-based) but I think this de-normalization (?) could be useful for performance
  • The reason behind having two columns (FromUsername and FromDomainId) is to enforce email sanity rules - I don't consider having a single column (FromAddress) as being appropiate

Having said all these, what are your opinions, dear readers?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

孤芳又自赏 2024-11-16 05:59:03

这是上面 @Philip Kelley 指出的“标准类型/子类型”模型的示例:

type/subtype model

你已经得到

  • SupertypeType。约束类型标识符的域的域表。

  • 超类型。常见的超类型。对于子类型实例之一的每个实例,此表中都存在一行。它包含对象 ID (SupertypeID)、对象类型标识符 (TypeID) 以及所有子类型通用的属性。

  • 子类型。每个子类型都存在一个表。它的主键是超类型表的对象 ID。对于超类型的每个实例,所有子类型表中不存在超过一行(当然,如果所讨论的实例属于基(超)类型,则可能没有行。每个子类型表各不相同,包含属性对于该特定子类型是唯一的。

要枚举所有元素,请查询仅超类型表。

如果您知道您只对特定子类型感兴趣,则只需从适当的子类型表中进行选择,根据需要连接超类型表即可获取所需的任何公共属性。

< /strong> 如果您需要整个集合的平面、非规范化视图,只需在子类型之间进行左连接:

select *
from Supertype     t
left join Subtype1 t1 on t1.SupertypeID = t.SupertypeID
left join Subtype2 t2 on t2.SupertypeID = t.SupertypeID
left join Subtype3 t3 on t3.SupertypeID = t.SupertypeID

现在您不需要多个查询。你用它来换取必须处理无效性。

Here's an example of the "standard type/subtype" model noted by @Philip Kelley above:

type/subtype model

You've got

  • SupertypeType. The domain table that constrains the domain of the type identifier.

  • Supertype. The common supertype. A row exists in this table for every instance of one of the subtype instances. It contains the object id (SupertypeID), the object type identifier (TypeID), and the attributes common across all subtypes.

  • Subtype. A table exists for each subtype. Its primary key is the object id of the supertype table. For each instance of the supertype, no more than one row exists across all the subtype tables (there may be no rows, of course, if the instance in question is of the base (super) type. Each subtype table varies, containing the attributes unique to that particular subtype.

To enumerate all elements, query only the supertype table.

If you know that you're only interesting in a particular subtype, you may simply select from the appropriate subtype table, joining against the supertype table as needed to get whatever common attributes you need.

Addendum. If you need a flat, denormalized view of the entire set, simply left join across the subtypes:

select *
from Supertype     t
left join Subtype1 t1 on t1.SupertypeID = t.SupertypeID
left join Subtype2 t2 on t2.SupertypeID = t.SupertypeID
left join Subtype3 t3 on t3.SupertypeID = t.SupertypeID

Now you don't need multiple queries. You've traded that for having to deal with nullity.

一个人的旅程 2024-11-16 05:59:03

您可以简化并使其更像标准类型/子类型模型,如下所示:

  • 以 MailMessags.Id 作为“类型”表主键开始,
  • 以 IsTemplateBased 作为类型指示符,以说明这是什么类型的电子邮件。 (我将其设为tinyint,以便将来可以在索引中使用以及用于更多类型。)
  • 删除TemplateId 和MailBodyId,您将不再需要它们。
  • 在“子类型”表 MailParams 中,将 MailMessageId 设置为 PK 并作为引用 MailMessages.Id 的 FK
  • 对 MailBody.MailMessageId 执行相同的操作

现在您只有一个,而不是三个不同的代理键(相应地,出现错误和混乱的可能性更大)来管理。

You can simplify and make it a bit more like the standard type/subtype model like so:

  • Start with MailMessags.Id as the “type” table primary key
  • Have IsTemplateBased as a type indicator, to say what kind of email this is. (I’d make it a tinyint, to allow for possible use in indexes and for more types in the future.)
  • Drop TemplateId and MailBodyId, you won’t need them.
  • In "subtype" table MailParams, set MailMessageId as the PK and as an FK referencing MailMessages.Id
  • Do the same thing for MailBody.MailMessageId

Instead of three different surrogate keys (and correspondingly greater chance for error and confusion), you now have only one to manage.

爱的那么颓废 2024-11-16 05:59:03

您需要子类型模型,并且还应该考虑消除这些空值所需的任何进一步分解。允许空值的表不是范式。

You need the subtype model and you should also consider any further decompositions you need to eliminate those nulls. A table that permits nulls is not in Normal Form.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文