views:

288

answers:

9

I inherited a system that stores default values for some fields in some tables in the database. These default values are used in the application to prepopulate control values. So, essentially, every field in every table in the database can potentially have a default value. The previous developer decided to store these values in a single table that had a key/value pair combo. The key represented by the source table + field name (as a varchar) and the default value as a varchar field as well. The Business layer would then cast the varchar field to the appropriate data type.

Somehow, I feel this is brittle. Though the application works as expected, there appears to be a flaw in the design.

Any suggestions on how this requirement could have been handled earlier? Is there anything that can be done now to make it more robust?

EDIT: I should have defined what the term "default" meant. This is NOT related to the default value of a field in the table. Instead, it's a default value that will be used by the application in the front end.

+3  A: 

A better way to go would be using SQL Server's built-in DEFAULT constraint.

e.g.

CREATE TABLE Orders
(
    OrderID int IDENTITY NOT NULL,
    OrderDate datetime NULL CONSTRAINT DF_Orders_OrderDate DEFAULT(GETDATE()),
    Freight money NULL CONSTRAINT DF_Orders_Freight DEFAULT (0) CHECK(Freight >= 0),
    ShipAddress nvarchar (60) NULL DF_Orders_ShipAddress DEFAULT('NO SHIPPING ADDRESS'),
    EnteredBy nvarchar (60) NOT NULL DF_Orders_EnteredBy DEFAULT(SUSER_SNAME())
)
Mitch Wheat
Please see edit
+1  A: 

If you want (and should!) use default values on the database, I would strongly urge to use the built-in DEFAULT constraint that's available on any field. Only that is really guaranteed to work properly - anything else is a hack solution at best.....

CREATE TABLE 
  MyTable(ID INT IDENTITY(1,1),
          NumericField INT CONSTRAINT DF_MyTable_Numeric DEFAULT(42),
          StringID VARCHAR(20) CONSTRAINT DF_MyTable_StringID DEFAULT 'rubbish',
      .......)

and so on - you get the idea.

Just learn this mantra: DRY - DON'T REPEAT YOURSELF - don't go out re-inventing stuff that's already there and has been heavily tested and used - just use it.

Marc

marc_s
Please see edit
Even so - you could easily read out all the defaults defined on a given table into your app code, and still use the rock-solid database column defaults.
marc_s
+3  A: 

Refactoring the schema now would be risky and disruptive so I would not recommend it (unless you absolutely need to do that to fix some pressing issue, but from what you say it doesn't look like you do).

Were you doing the design from scratch, I'd recommend one defaults-table per real-table, with a single row recording the defaults with their real column names and types. Having several tiny tables scares some DBAs, but it's not really any substantial performance hit in my experience, and it sure does make the system sounder and more robust as you desire.

If you want to use SQL's own DEFAULT clauses as other answers recommend, be sure to name those explicitly, otherwise altering them when a default changes can be a doozy. Personally, I like to keep the default values separate from the schema's metadata, especially in a system where updating or tweaking a default value is a much more common and should-be-innocuous operation than the momentous undertaking of metadata/schema changes!

Alex Martelli
what's wrong with the built-in DEFAULT constraint?
Mitch Wheat
Is there a situation where this might be preferable to using the DEFAULT constraint mentioned above?
Jeff Barger
Thanks for the input. I agree this would have been a better approach. Given that the system is already in place, do you recommend anything with the existing design to make it more scalable?
Alex Martelli
@unknown, I think it might help (and be a minor-enough refactoring to be worth considering) to have different tables (or columns in a table, but that may be less handy) for default values of different types, to avoid the casting -- feasible only if the number of types used in the defaults is reasonably small, though.
Alex Martelli
@Jeff, sure, if default values are as nearly-immutable as other aspects of the schema and subject to exactly the same authorization issues, it's not worth factoring them out of the schema; however in my experience I often found that such conditions may not hold (but if one is sure they do in a given case, then by all means use the handy [named;-)] DEFAULT constraint!).
Alex Martelli
@Alex - It's a good idea to have different columns representing different data type defaults (Ex: varcharDefault, dateTimeDefault, xmlDefault etc). Not sure how easy this change would be though.
@All - Also, I am trying to understand the justification behind this design
@unknown, justification behind what design -- the one you inherited? It's a guess, but I imagine its author felt that by making the defaultvalues table "universal" he'd guarantee never having to rework it in the future, or something like that.
Alex Martelli
+1  A: 

If its a case of UI defaults - the following questions come up.

  • How 'dynamic' or generic is your schema.? Does the same schema support multiple front-ends - i.e. the same column in the Db-table supports 2 front-ends - each with multiple-defaults?
  • Do multiple apps use your DB? In that case having the default defined in the DB could still help
  • Its possible to query the Data-dictionary to get default info for each column.
  • If a UI field does not have a corresponding db-column, then your current implementation will be justified in such cases
  • One downside is more code is needed to handle and use this table.
  • If it was a one-off application and this default 'intelligence' was not leveraged across multiple-apps - thats a consideration
  • Its more like a 'frameworky' kind of thing to do - though I'd say its quite non-standard, and would be done on the web-layer.
blispr
+2  A: 

If the requirement was that the default selection of a given control be configurable and the "application works as expected" then I don't see a problem. You didn't elaborate on the "flaw" in the design.

Well, isn't storing everything as a varchar(max) a bad idea to begin with?
+1  A: 

I think the real answer here depends heavily on how often these default values change. If default values are set once when the database is designed, then DEFAULT constraints make sense. If some non-technical person needs to change them every couple of months, I really like the design presented.

Where it becomes brittle is when you have a mismatch between the column names or data types and the default values in the Defaults table. If you code a careful interface to manage the Defaults table values, this shouldn't be a problem.

Bill
A: 

The idea (not necessarily the implementation) makes sense if you want to keep the application defaults separate from the data, allowing different apps to have different defaults.

This is generally a good thing, because many databases inevitably spawn secondary applications (import jobs, if not anything else), where you do NOT want the same defaults (or any defaults at all); and in principle, a defaults table can support this.

What I think makes this implementation less-than-ideal is that while the defaults are MOSTLY data-driven, the calling application either needs its own set of defaults IF the defaults are not specified in the table or terminate.

If the former is employed, this could introduce a number of headaches when you're trying to track down bugs, especially if you don't have good audit tables keeping track of which user/application inserted/updated which rows on which tables.

Disclaimer: I'm generally of the thought that columns ought to be NULLable and w/o defaults, except where it absolutely makes sense from a data point of view (id/primary key, custom timestamp, etc.). If a column should never be NULL introduce a constraint forbidding NULLs, not a concrete default.

hythlodayr
A: 

If the table of default values is what irks you, here's some food for thought:

Rather than stick to dogma about varchar(max) or casting strings or key/value tables - a good approach is to ask what is a better solution?

From your description, it seems like this table contains few rows, and has only two columns: key and value.

I should ask - is the data in this table controlled from an administrative UI? Perhaps this is the reason behind the original design decision to make it a table.

If type-safety is an issue, you could consider the existence of a "type" column and analyze how the code would need to be changed.

I wouldn't jump to conclusions about "good" or "bad" until you really analyze WHY the system is implemented this way.

Jeff Meatball Yang
The table contains a LOT of rows and yes 2 columns of interest. I am wondering why this approach when having 1 default table for each table approach would have been better (wouldn't need varchar(max)). I am trying to understand the justification and if it's a standard approach.Yes, defaults can be changed by the end user.
+4  A: 

That schema design is fine. I've seen it used in commercial apps and I've also used it in a few apps of my own where the users needed to be able to change the defaults or other parameters around fields in the application (limits, allowable characters etc.) or the application allowed the users to add new fields for use in the app.

Having it in a single table (not separate default tables for each table) protects it from schema changes in the tables it supports. Those schema changes become simple configuration changes in this model.

The single table makes it easy to encapsulate in a Class to serve as the "defaults" configuration object.

Some general advice: When you inherit a working system and don't understand why something was designed the way it is - the problem is most likely your understanding, not the system. If it isn't broken, do not fix it.

Specific advice on the only improvements I would recommend (if they become necessary): You can use the new SQLVARIANT field for the value rather than a varchar - it can hold any of the regular data types - you will need to add support for casting them to the correct data type when using the value though.

Ron

Ron Savage
I agree completely - I'll call this scenario "The Engineer's Way vs. the Engineer's Temptation" - we want It (whatever it is) to be clean and elegant, yet we should really understand It before we change it - or bad things happen.
Jeff Meatball Yang
The red flag for me was this table is growing at an alarming speed (as it has field level info). Is this common and standard. I am not a DB guy and might be overreacting.
@Ron - Can you please point me to any schema that is available on the web that does something similar to this (I am not sure if the commercial apps you are referring to is open source for me to view the design)
The commercial app is really old and not open source, named CIX - it is a retail item hosting system. My own field configuration table was for a configurable web-wizard app to allow users to add new retail items to that system. The table was a bit more elaborate. :-)http://dot-dash-dot.com/files/nicc_fields.txt
Ron Savage