I have to import the content of 4 tables from an old database into SQL 2005 for easier reporting.
Products contains the id and product name, ProductProperties contains a variable number of properties for each product, Ingredients contains a variable number of ingredients for each product, and IngredientProperties contains the same properties as the product, specified for each ingredient.
alt text http://www.freeimagehosting.net/uploads/15068ece48.png
With black I marked the relationships between the tables in the current design, and with red and green the possible foreign keys of IngredientProperties table.
Currently I am retrieving all the rows from IngredientProperties for a given IdProduct and generate the report from that, but I would like to use the foreign keys for allowing future updates of the data.
What is the recommended design of the relationships of the IngredientProperties table for better usage with Linq?
Two sample reports:
// IdProduct = 1
Price Density
A1 25 10
A2 56 14
// IdProduct = 2
Price Density Opacity
B1 87 21 60
B2 50 31 70
B3 12 10 90
Your red arrows imply that a product could not have any rows in IngredientProperties unless the product had at least one matching row in ProductProperties. Does it make sense that a product’s ingredients can’t have a density until the product has a density? This restriction does not exist with only the “black arrow” FKs.
(Does it even make sense to repeat the properties for each product? Does the density, opacity or price of ingredient A1 vary depending on which product it’s incorporated into?)
The FK from IngredientProperties to Ingredients makes sense, but it should be a single aggregate key, not two separate FKs, which implies that the PK on Ingredients should also be an aggregate key, and the same applies to ProductProperties.
Edit:
Thanks for the update. As I implied earlier, adding Foreign Keys to match the red/green arrows in your diagram will create constraints within the database that do not currently exist, which in turn could break existing code that uses the database if it, e.g., inserts into ProductProperties before inserting ingredients.
By using an aggregate key, you are basically saying that only one (ProdID, IngredientID) can exist in the Ingredients table. It looks like that’s already being done. If the circled header items indicate indexes, then the data is already well-indexed.
I suspect that the “top” red arrow is incorrect, actually. There are two PropertyKey rows, but I don’t think they represent the same thing, since there’s a separate PropertyValue in each table. One pair represents properties of products, the other properties of ingredients, so linking them together will just cause confusion.
I’m still not 100% sure what you’re looking for, but here are my recommendations:
The indexes are all that’s needed for efficient join queries between tables. The foreign keys serve to maintain “referential integrity.” For example, they prevent you from inserting properties for an ingredient that doesn’t exist.
There are several things you could do to normalize this database as well, but I would not change it unless you have specific problems that need to be fixed.