Reputation: 381
First of all, I do realize that there are plenty of questions regarding this problem and there is a good chance that I already know one of the answers, but after I've tried a couple of them, none of them worked for me.
In my application I am handling communication between user and customer. Both users and customers can have multiple e-mail addresses. Also, both users and customers can be assigned to multiple conversations at the same time. After user or customer sends an e-mail message, system receives information about that and creates a ConversationMessage with basic info about the message and EmailMessage with specific data (subject, FROM, TO etc.).
Right now, fields FROM and TO are just varchar fields with e-mail addresses. I would like to change it so that FROM and TO fields are foreign keys. I was planning to create an EmailAddresses table that would store basic info about the address and UserEmailAddresses and ContactPersonEmailAddresses tables with specific info about address (like host, port etc.), but I realized that EmailAddresses table would contain just an Id. Is it a good approach? Am I missing something?
Are there any better solutions to this kind of problem?
Thank you for any help!
Upvotes: 0
Views: 392
Reputation: 5636
There are numerable issues with the design but let's limit the discussion to the email addresses. You store the addresses in two tables. This, unsurprisingly, is causing problems.
An email address is an entity. Store them in a table. Anywhere a single address is needed, place a FK to the one address table there. Where multiple addresses is or may be needed, place an intersection table there.
create table EmailAddresses(
ID int auto_generating primary key,
Addr varchar not null unique,
Active bool
);
Are such fields as Login, Port, etc. really attributes of an email address? Maybe you could clarify those if you would.
Then the tables UserEmailAddresses and ContactEmailAddresses would be intersection tables and look something like this:
create table [User|Contact]EmailAddresses(
UserID int not null references [Users|Contacts]( ID )],
AddrID int not null references EmailAddresses( ID )
);
As an email message can only have one "From" value, that would be in the EmailMessages row as it is now except it can now be a FK to the one address table. A message may have one or many "To" values so that would be implemented also as an intersection table:
create table EmailTo(
EmailID int not null references EmailMessages( ID )],
ToID int not null references EmailAddresses( ID ),
ToType enum( To, CC, BCC )
);
There are probably other requirements that would require some constraints on any or all of the tables above but those depend on your usage. For example, even though email applications allow the same address to exist more than once in a From list, you may want to catch and restrict such occurrences. This would be implemented by a unique constraint on (EmailID, ToID)
Possible extensions would be the addition of email lists which themselves contain a group of addresses. That would require the EmailAddresses table to split but because all addresses are now located in one table, such a redesign would certainly be easier that having them located in two tables.
Upvotes: 1