我正在创建一个消息系统作为宠物项目,其中包括具有文件附件的功能。这将在我的网站上用于内部邮件系统。
这个系统的一个特点是我想维护上传的每个文件的MD5校验和,这样如果上传了重复的文件,这两个链接就会引用同一个文件。
到目前为止,我已经提出了以下建议:
Message
----------
MessageID (PK)
SenderID (FK)
RecipientsID (FK)
AttachmentsID (FK)
Subject
MessageText
DateSent
Recipient
----------
UserID (FK)
MessageID (FK)
Attachment
----------
ID
Name
MessageID (FK)
FileID (FK)
File
----------
ID
Checksum
LastAccessDate
AccessCount
因此,您将能够拥有多条消息,每封消息都可以包含多个附件。而且,为了节省我们服务器上的空间,因为我的用例会让用户上传许多相同的文件,不同的附件可以引用同一个文件。
我的问题是,Message表是否应包含某种RecipientsID?或者我的收件人表引用MessageID就足够了吗?
Message表上的AttachmentsID的相同问题。我应该有某种AttachmentsID吗?或者,Attachment表引用MessageID就足够了。
如果附件和收件人都知道他们属于哪个邮件,那么邮件是否可以没有对其附件或收件人的任何引用?或者我应该采取另一种方式吗?
我很想知道一些资深的SQL人员会如何制定这种模式。
编辑:我希望每封邮件有多个收件人和多个附件。如果不清楚,我很抱歉。
正是在这些一对多的关系中,我正在努力理解我是否以最好的方式去做。
答案 0 :(得分:2)
您的所有问题都取决于您的具体业务规则。邮件可以有多个收件人吗?如果是这样,那么您无法将收件人ID存储在消息表中,因为这样只允许您为每封邮件存储一个收件人。通过这种逻辑思考你的每一种情况,它将有希望变得更加清晰。
在RDBMS中建模关系的标准方法是:
1对多:“many”表中包含“1”表的PK。例如,一个订单可以有许多订单行,因此每个订单行的行都有一个order_id
多对多:两个主表之间存在“链接”表,其中包含两个主表的PK。这些组合的PK通常构成链接表的PK。例如,在大多数情况下,可以将消息发送给多个用户,并且用户可以向他们发送多个消息。在这种情况下,您具有多对多关系,因此您将拥有Users表(user_id,name等),Message表(message_id,message_body等)和Message_Recipients表(message_id,user_id)。
1对1:这类似于从OO角度进行子类化。我可能在我的数据库中有建筑物,它跟踪某些数据,然后除了这些数据之外,一些建筑物也可能是House,它们跟踪其他数据。在这种情况下,两个表共享相同的PK。
我不会在这里进入层次结构,因为它们可以通过几种不同的方式建模,最佳模型通常取决于系统的特定因素。
答案 1 :(得分:1)
这里有很多好的答案,但让我更直接:
Message表中是否包含一些 一种收件人ID?
没有
或者是否足以让我的收件人 表引用MessageID?
是
AttachmentsID的相同问题 消息表。我应该有 某种AttachmentsID?
没有
或者附件是否足够 表引用了MessageID?
是
没有消息可以 任何对其附件的引用或 收件人,如果两个附件和 收件人知道他们的消息 属于?
是
答案 2 :(得分:0)
您可以将Recipients表全部放在一起。这是多余的,因为Message表中的RecipientID保存该值。除非你想拥有一个以上的收件人,否则必须采用另一种方式。
关于附件,附件表最好是指消息表,而不是相反。如果消息表具有附件ID,则会将其限制为每个消息一个附件,这可能很好,但如果要将其扩展为允许多个附件,则可能会限制。
另一方面,只有一个附件可以让您获得附件ID以及消息,并且您可以加入查询行,以便在一个查询中获取所有内容。保存一些代码行。
总而言之,'minimalistic'方式是拥有一个收件人和一个附件,在这种情况下,您将删除附件表中的收件人表和messageId。 最广泛的方法是拥有多个收件人和附件,在这种情况下,您将在邮件表中删除recipientId和attachmentId。
答案 3 :(得分:0)
根据您计划存储文件的方式,您需要考虑上传的文件名。我知道在Windows上有一个访问文件的最大路径长度(路径包括完整的文件名和扩展名)。因此,您可能希望执行诸如为文件指定任意名称并将实际文件名存储在File表中。您可能还想考虑上传文件的MIME类型,以便在用户想要查看文档时通过网站提供它。可以根据扩展名或类似内容进行阅读并将其存储起来,或者在网站将文件提供给用户下载时查找。
答案 4 :(得分:0)
Message
---------
msg_id (PK)
sender_id (FK to users_id)
metadata...
Users
---------
user_id (PK)
address (How to locate the user for routing purposes)
metadata....
Attachments
----------
attachment_id (PK)
md5 (possibly UNIQUE, but beware of collisions)
file_sys_ref (a way to find the attachment file in the file system)
meta_data...
Recipients
----------
message_id (FK -> Messages)
user_id (FK -> Users)
meta_data...
PRIMARY KEY (message_id, user_id)
我将文件存储在filesytem中,而不是作为数据库中的BLOB存储,但那只是我。我发现通过外部文件传输机制(ftp,scp,HTTP POST等)传输它更容易,然后编写自己的文件传输机制到数据库中。
答案 5 :(得分:0)
Actaully facebook也使用类似这样的,这是详细信息。