views:

35

answers:

3

Someone suggested moving a table full of settings, where each column is a setting name(or type) and the rows are the customers & their respective settings for each setting.

ID | IsAdmin | ImagePath
------------------------------
12 | 1          | \path\to\images
34 | 0          | \path\to\images

The downside to this is every time we want a new setting name(or type) we alter the table(via sql) and add the new (column)setting name/type. Then update the rows(so that each customer now has a value for that setting).

The new table design proposal. The proposal is to have a column for setting name and another column for setting.
ID | SettingName | SettingValue
----------------------------
12 | IsAdmin        | 1
12 | ImagePath   | \path\to\images
34 | IsAdmin        | 0
34 | ImagePath   | \path\to\images

The point they made was that adding a new setting was as easy as a simple insert statement to the row, no added column.

But something doesn't feel right about the second design, it looks bad, but I can't come up with any arguments against it. Am I wrong?

+1  A: 

The second approach actually resembles a dictionary. I found this to be a more convenient choice for an application I am working on for the reasons you mentioned. There are a few caveats to this approach, so you need to be careful about them:

  • Keep your key strings static, never rename.
  • Make sure each time the settings dictionary is retrieved you update it to the newest version (usually by adding keys and setting default values/prompting the user).
  • It's tricky to mix string and e.g. decimal data, you'll either need to choose one or provide multiple, nullable columns so you can store data in the appropriate format. Keep that metadata around somewhere.
  • The code that deals with the dictionary should wrap it in a strongly typed fashion, never expose it as a real dictionary (in the sense of a datastructure), provide a class instead.
Johannes Rudolph
I noticed that it was dictionary as well, it may end up being better to wrap in a hash with the setting name as the key and value as the value(typed in as object, but that'll open up another can of worms). Thanks for the input.
Chris L
A: 

Using column names to distinguish settings is usually a terrible idea. The entity you are dealing with is the SETTING, and it has the attributes NAME and VALUE. If you need to use the same name in different contexts, make the SETTING hierarchical, i.e. each setting except the root gets a parent. You customers could then have the root as their parent, and the path under each customer would be the same for each setting. You can use different columns for additional data types if you want.

FelixM
+1  A: 

This is a variation of an "Entity Attribute Value" schema (Joel and random SO question)

It has a few pros and more cons, and it pretty much guaranteed to end in tears.

gbn
I think using EAV on settings is ok. Designing your complete database around EAV is a completely different story and not what the OP asked about. But I fail to see how fundamentally different document database are from your perspective, and I fail to see why using them would be guaranteed to end in tears too.
Johannes Rudolph
@Johannes Rudolph: For a simple system settings table, then yes. Just like appsettings in web.config, say. However, like web.config, you use dedicated sections for more complex settings: you don't expand appsettings. And eventually, it will get worse because someone will think "what a great idea". Saying that, I've used them but you have to be careful...
gbn
Thanks for the heads up this was a (rough) version of EAV, between the links and google, I should get something. There does appear to be some issues with referential integrity. Such as creating a setting DefaultReportID, 10 when in the Report Table on 1 thru 9 exists.
Chris L