数据库表设计 - 邮件类型

时间:2017-08-06 10:14:21

标签: sql sql-server tsql database-design constraints

我正在建立一个Mail数据库,MAIL表的设计如下:

ID (Surrogate PK)

Recipient/Sender (Coming as FK from `REGISTERED_USERS` table - Recipient if outgoing mail and Sender if incoming mail)

Dispatch/Receive Date

Status (Coming as FK)

PostType (Whether it is Sent or Received mail)

问题

我的问题出在状态列中,因为传出或接收邮件的状态不同(例如,收到传入邮件的已接收邮件和已订购邮件,已盖章邮件,已转发邮件等)。

我的方法

我尝试过触发器来实现这一点,但我想确保使用一些约束条件有更好的解决方案/设计吗?非常感谢!

3 个答案:

答案 0 :(得分:3)

这可能是基于意见但是......

您不应在同一列中存储不同的数据。您应该将所有传入/传出列拆分为两个,并仅为不同类型的邮件填充相关的列

在您的解决方案中,如果您在Recipient/Sender列中有约翰,则在检查PostType列之前,您不知道John是收件人或发件人。那不是很好的设计。每列应该是自我识别的。

我建议将您的设计更改为:

ID
Sender 
Recipient
DispatchDate
ReceiveDate
IncomingStatus
OutgoingStatus
PostType

如果您真的需要组合数据来显示某个地方,您可以为此目的创建一个视图:

SELECT 
   CASE WHEN PostType = 1 THEN Sender ELSE Recipient END AS [Recipient/Sender] 
   CASE WHEN PostType = 1 THEN DispatchDate ELSE ReceiveDate END AS [Dispatch/Receive Date]

等。

(或将它们添加为计算列)

此外,通过分隔列,您可以为自己创建一个空间,例如,如果将来需要,也可以存储外发邮件的收件人。

答案 1 :(得分:1)

如果两种类型具有完全相同的属性,并且您可以通过添加StatusType属性或类似属性来区分它们,则可以将两种状态类型存储在一个表中。

如果OutgoingStatus的属性与IncomingStatus的属性不同,那么您应该考虑创建两个单独的表。

答案 2 :(得分:1)

执行此操作的一种方法是在Mail表上实现CHECK约束。

你可以像这样添加一个CHECK约束:

ALTER TABLE Mail
ADD CONSTRAINT CK_MAILSTATUS 
CHECK ((PostType = 'Outgoing' AND [Status] IN('Ordered', 'Stamped', 'Dispatched')) OR (PostType = 'Incoming' AND [Status] IN('Received')))

之后,您将无法将记录插入到不符合CHECK约束条件的Mail表中。如果您尝试这样做,则会出错:

  

INSERT语句与CHECK约束冲突" CK_MAILSTATUS"。冲突发生在数据库" YourDatabase",table" dbo.Mail"。