views:

111

answers:

4

I am facing this question in a new little project: The system to be built will allow user to add new columns to a table in the system, and then the user will be able to maintain the data, I think there is two ways to implement this: 1) create a few tables including "columns" table with "columnName" "columnValue" "datatype" etc to store the column definition, aonther table "XXCoumn" to store the value of the column (entered by user), and user a store procedure to query/update column data. 2) create the column in the table schema when user enter a new column, then the maintain of the table data is just as normal

which way do you guys reckon? or any new suggestion?

Some additional info: the data volumn is small, and I need to create reports.

A: 

If this is centrally hosted by you, I would suggest NOT allowing user-input data to change the schema of the database (i.e. drive the creation of new tables).

Rather you may want to look into using XML fields in SQL to store variable field names of data, or a more generic table structure... this technique works pretty well if we're not talking crazy amounts of data...

routeNpingme
xml is a good idea, but it make reporting difficult
peanut
A: 

Is it possible you're looking at your solution sideways? It sounds like you need a mapping table (sort of like your #1). You have a table, say "objects" for example, a table called "properties" which holds what you're calling columns and then a table that holds the values, so it just has object_id, property_id, value.

To put in a smarter way than I said it, take a look at the Entity-attribute-value model.

Tom
+1  A: 

"The system to be built will allow user to add new columns to a table in the system..."

Really - that's the user story? Sounds like you've already made up your mind on the solution, to me.

Whether it's a good idea or not to allow a user to extend schemas is pretty context dependent. I'd have little problem in an admin-like, limited use way. But it'd be a horribly bad idea in a MySpace type way. I suspect your situation lies somewhere between those 2 extremes.

Extending the schema would lead to greatly more efficient queries - as you could add indexes and such - but it does expose some relational rules on your users. Also, the extension would (probably) lock the entire table and concurrent edits would need to be dealt with.

Mark Brackett
I should explain more of the background, but it is a real requirement to add additional columns on the fly.
peanut
+2  A: 

Any good recommendations would require a much better understanding of your requirements, but here are some comments on the options you mentioned, as well as some additional thoughts.

1) Entity-Attribute-Value (EAV) Design: This is the option you describe where you have a table that has columns for ColumnName, Type and Value. This option has the advantage of being able to accomodate unlimited new columns easily, but I have found it to be painful when the time comes to retrieve meaningful data back. For example, say you have rows in this EAV table for {Color, varchar}{Red, Green, Blue}, and {Size, varchar}{Small, Medium, Large}. If you want to find all the small green items, you need something like this (untested SQL of course):

SELECT * 
FROM ITEMS 
WHERE ITEMID IN (SELECT ITEMID 
                 FROM ITEM_ATTRIBUTES ATT INNER JOIN ITEM_VALUES VLS
                     ON ATT.AttributeID = VLS.AttributeID
                 WHERE ATT.ColumnName = 'Color' AND VLS.Value = 'Green')
  AND ITEMID IN (SELECT ITEMID 
                 FROM ITEM_ATTRIBUTES ATT INNER JOIN ITEM_VALUES VLS
                     ON ATT.AttributeID = VLS.AttributeID
                 WHERE ATT.ColumnName = 'Size' AND VLS.Value = 'Small')

Contrast this with having actual columns on the items table for color and size:

SELECT *
FROM ITEMS
WHERE COLOR = 'Green' AND SIZE = 'Small'

In addition, you will have a difficult time maintaining data integrity, if that is important for this app (and it is almost always important, even when you are told otherwise). In the example above, you will need to implement extra logic if "Color" should be limited to Blue, Green, and Red. Also, you will need to implement even more logic if certain colors only come in certain sizes (example - blue items are only available in small and medium)

2) User-Defined Columns: Just giving the user the ability to add additional columns to the table has the advantage of making data retrieval simpler, but all the data integrity issues remain. Also, your app usually requires extra logic to deal with the unknown columns.

3) Pre-Existing Custom Columns: I have worked with a few apps, such as CRMs, that provide a dozen or more columns already in place for user definition. Basically, the designers put in columns like "Text1","Text2","Text3","Number1","Number2", etc. The users then provide header and description information for these columns, and that is what the app uses for display purposes. This model has the advantage of easy data retrieval, as well as a pre-defined DB schema which should simplify app logic. Data integrity issues remain, however. The other obvious downside is that you will run out of pre-defined columns, which is what you are usually trying to avoid with this type of solution.

As with most design issues, there are tradeoffs to each solution. My experience has been that while many users/clients say they want solutions like these, in reality they are simply trying to ensure they don't get trapped with an app that can't grow with their needs. I have found that there are actually very few places where a design like this is needed. I can almost always create a design that addresses the expansion desires of the client without putting them into the role of database designer.

JeremyDWill
Thanks for the thougtful comments. The additional columns could be any data type(although most of them should be list item - string, but it could be datetime etc), and the system need to adapt to different clients who need to define different columns so option 3) is out.
peanut
I am hesitated between option 1) and 2)
peanut