I am writing a addressbook module for my software right now. I have the database set up so far that it supports a very flexible address-book configuration.
I can create n-entries for every type I want. Type means here data like ’email’, ‘address’, ‘telephone’ etc.
I have a table named ‘contact_profiles’.
This only has two columns:
id Primary key date_created DATETIME
And then there is a table called contact_attributes. This one is a little more complex:
id PK #profile (Foreign key to contact_profiles.id) type VARCHAR describing the type of the entry (name, email, phone, fax, website, ...) I should probably change this to a SET later. value Text (containing the value for the attribute).
I can now link to these profiles, for example from my user’s table. But from here I run into problems.
At the moment I would have to create a JOIN for each value that I want to retrieve. Is there a possibility to somehow create a View, that gives me a result with the type’s as columns?
So right now I would get something like
#profile type value 1 email name@domain.tld 1 name Sebastian Hoitz 1 website domain.tld
But it would be nice to get a result like this:
#profile email name website 1 name@domain.tld Sebastian Hoitz domain.tld
The reason I do not want to create the table layout like this initially is, that there might always be things to add and I want to be able to have multiple attributes of the same type.
So do you know if there is any possibility to convert this dynamically?
If you need a better description please let me know.
You have reinvented a database design called Entity-Attribute-Value. This design has a lot of weaknesses, including the weakness you’ve discovered: it’s very hard to reproduce a query result in a conventional format, with one column per attribute.
Here’s an example of what you must do:
You must add another
LEFT OUTER JOINfor every attribute. You must know the attributes at the time you write the query. You must useLEFT OUTER JOINand notINNER JOINbecause there’s no way to make an attribute mandatory (the equivalent of simply declaring a columnNOT NULL).It’s far more efficient to retrieve the attributes as they are stored, and then write application code to loop through the result set, building an object or associative array with an entry for each attribute. You don’t need to know all the attributes this way, and you don’t have to execute an
n-way join.You asked in a comment what to do if you need this level of flexibility, if not use the EAV design? SQL is not the correct solution if you truly need unlimited metadata flexibility. Here are some alternatives:
TEXTBLOB, containing all the attributes structured in XML or YAML format.EAV and any of these alternative solutions is a lot of work. You should consider very carefully if you truly need this degree of flexibility in your data model, because it’s hugely more simple if you can treat the metadata structure as relatively unchanging.