There are two solutions, each of which has its own advantages and disadvantages:
Option 1: Genericity
a table of parameters for the entire system, defined as follows:
Create table tbGlobalOptions ( OptionName Varchar(255) Identity, OptionValue Varchar(255), OptionType varchar(255) isLocked bit
And the table of user options:
Create table tbUserOptions ( OptionName varchar(255) UserID bigint, OptionValue varchar(255), Active bit )
The code contains an enumeration corresponding to the OptionName column, so parsing parameters from the code is trivial.
Minuses:
- type safety can only be implemented using constraints or triggers (which is clearly more difficult to maintain than column types).
- it’s more difficult to use saved parameters directly from the database (since the parsing logic lives in the application code)
- getting all parameters for a specific user is more expensive (you cannot just select a user line)
Option 2: Specialization (and Strong Typing)
Strongly typed options table containing one column for each option
Create table tbOptions ( UserId bigint, -- 0 for global defaults Option1 int, Option2 varchar(max) Option3 int, ... Option426 bit )
The type of security is certainly a good thing, but here it has huge costs:
- adding a new option requires changing the scheme
- the stored procedures used to update the table will contain a lot of duplicated code, since the logic (for example, the isLocked mechanism or some additional entries that you can add) must be repeated over and over for each field. Here's how you ended up with stored procedures containing 1,500 arguments.
- This solution does not scale well because the table cannot have an unlimited number of columns (see maximum values for SQL Server 2008 here for example).
If you have 5 options, and if that number is likely to remain unchanged over time, the second solution has its advantages.
If, on the other hand, you plan to eventually use thousands of options, this sound, as if without problems, for me: go to the pedigree!
In the application code, your problem is quite easily resolved using the general method:
OptionEntity<T> GetOptions<T>(string OptionName, T defaultvalue);
Change the response to Brian's comment below:
And yes, if there are 10,000 values to store, there will be 10,000 columns. This is true for every table you will ever write. The options table is nothing special. Nothing.
It all depends on the level of abstraction that we have chosen. How could you maintain a chessboard position, for example? You can clearly use a table of 64 columns (64 values → 64 columns) or you can use a design with only 4 columns (game identifier, x, y, content). Don't you think that both may be appropriate depending on the situation?
In this particular case, if the parameters can be created on the fly, or if their numbers grow exponentially, these parameters are to some extent just another type of data. And you don't want to store data in your schema, right?