What is the right way to do flexible columns in database? - mysql

Im storing columns in database with users able to add and remove columns, with fake columns. How do I implement this efficiently?

The best way would be to implement the data structure vertically, instead of normal horizontal.
This can be done using something like
TableAttribute
AttributeID
AttributeType
AttributeValue
This application of vertical is mostly used in applications where users can create their own custom forms, and field (if i recall corretly the devexpress form layout allows you to create custom layouts). Mostly used in CRM applications, this is easily modified inproduction, and easily maintainable, but can greatly decrease SQL performance once the data set becomes very large.
EDIT:
This will depend on how far you wish to take it. You can set it up that it will be per form/table, add attributes that describe the actual control (lookup, combo, datetime, etc...) position of the controls, allowed values (min/max/allow null).
This can become a very cumbersome task, but will greatly depend on your actual needs.

I'd think you could allow that at the user-permission level (grant the ALTER privilege on the appropriate tables) and then restrict what types of data can be added/deleted using your presentation layer.
But why add columns? Why not a linked table?

Allowing users to define columns is generally a poor choice as they don't know what they are doing or how to relate it properly to the other data. Sometimes people use the EAV approach to this and let them add as many columns as they want, but this quickly gets out of control and causes performance issues and difficulty in querying the data.
Others take the approach of having a table with user defined columns and give them a set number of columns they can define. This works better performance wise but is more limiting interms of how many new columns they can define.
In any event you should severely restrict who can define the additional columns only to system admins (who can be at the client level). It is a better idea to actually talk to users in the design phase and see what they need. You will find that you can properly design a system that has 90+% of waht the customer needs if you actually talk to them (and not just to managers either, to users at all levels of the organization).
I know it is common in today's world to slough off our responsibility to design by saying we are making things flexible, but I've had to use and provide dba support for many of these systems and the more flexible they try to make the design, the harder it is for the users to use and the more the users hate the system.

Related

Complex database design for many checkboxes

I'm currently creating a website for a local hospital. The problem I am currently facing: The website has too many checkboxes and fields that are enabled/disabled depending on the checkbox.
This is url to the website: http://ali.ezyro.com/adan/myForm.php
Since I have little experience with databases, what is the best way to design the database to hold all the data of this document?
This is a case where a relational database may not be your best option - it all depends on how the data is used within the system.
The straightforward option is to design one (very wide) table for each patient. Each attribute is modelled as a column; multi-valued attributes (check boxes) have one column for each valid option, single-valued attribute which require a lookup from a list of valid options use a foreign key to a table holding the valid lookups (e.g. in the patient table, you have a column called cervical_collar_id, and you have a separate table called cervical_collar_values with 1 - prehospital, 2-on arrival, 3-not required).
This allows you to store the data, and query it efficiently using standard SQL (find all patients who arrived with a prehospital cervical collar, for instance).
The "if you select box x, then box y becomes mandatory" logic should probably live in the application, not your schema.
But this is a difficult design to work with - adding attributes to the patient record is non-trivial. Wide tables are usually a bad sign.
You might decide that's a bad thing, and go for "entity/attribute/value" design. Lots of Stack Overflow answers will tell you the benefits and drawbacks of this - Google is your friend. TL;DR: even moderately complex queries become almost impossible.
You might instead decide to store the data as a document - most database engines store JSON and XML, and allow you to query this data efficiently. It has the benefit of being easier to develop, and easier to change - but you lose the built-in validation that the relational model gives you.

Database design: Custom data layout and rights management

I'm workling on a project for my University and im a little curious about my current database design:
First of all, what is the common naming practice for a database table: singular or plural? I once read something about i but i cannot remember it?! (e.g. table: user or users)
The second question is a little mor specific to the project:
The users can login into the website an have to choose 10 elements out of a list and attach each of the elements a priority from 1 to 4. My first try was to save the choice of the user in a single row as a CSV (e.g. 1,2,3;4,5,6;7,8;9,10 which represents the choice of element 1,2,3 with priority 1 etc.). The second attempt was to save each choice as a single entry like: [user_id]|[choosen_element]|[choosen_priority]. What do you think is the better variant or is there a even better one that i havent thought of?
The third question is more about the login and rights management:
The elements that the users can choose from are in groups. Each element can be in multiple groups. There are moderators who have the same groups that the elements have or a subset of it, and they can edit all elements of the group they are in posession of. Besides the groups there are also the rights for the users e.g. user, moderator, admin etc.
In my last design i defined the rights of the users as part of the groups table so that every user that is in the moderators group can edit items of the groups that he is also in.
In my first attempt i had the groups and the rights in a seperate table with a seperate logic in my application!
Is it better to seperate the aplication rights from the groups?
Here is a plot of my current layout if i missed something, or if somebody just likes to look at pictures ;)
http://screens.rofln.de/2012-06-19-4f3o3A.png
Thanks!
Btw.: Im working with PHP and a MySql if someone whants to know!
This is subjective, but if you go by conventions supplied by popular ORMs, it seems pluralized is pretty common. I don't think which you chose matters, only that you are consistent once you have chosen.
A record representing each choice makes most sense. This allows for ordering as well as queries to find highly rated elements, etc. Finally, reading the data in your application, and varying how it is displayed, will be easier since you'll be working with a list of items rather than a packed value.
This is hard to answer, since I'm not familiar with your problem domain. I'd recommend developing use cases and then applying them to your proposed model to see where the cracks are.
It does not matter whether you use singular or plural, what matters is that you are consistent in your use of the standard.
Comma separated values in MySQL are bad, mostly because it is not a congruent way of using a relational database. A standard database relationship, or a many-to-many table is a better idea.
When you make your rights management system more flexible, it becomes more complex. A good heuristic in this case is to build the simplest system that satisfies your requirements, but no simpler.
Speaking of simplicity, why do you have a separate table for userdata? Do you expect some user to have two sets of names and details?

Multilingual database design pattern

I'm currently working on Blog-Software which should offer support for content in multiple languages.
I'm thinking of a way to design my database (MySQL). My first thought was the following:
Every entry is stored in a table (lets call it entries). This table
holds information which doesn't change (like the unique ID, if it's
published or not and the post-type).
Another table (let's call it content) contains the strings
(like the content, the headline, the date, and author of the specific
language).
They are then joined by the unique entry-id.
The idea of this is that one article can be translated into multiple other languages, but it doesn't need to be. If there is no translation in the native language of the user (determined by his IP or something), he sees the standard language (which would be English).
For me this sounds like a simple multilingual database and I'm sure there is a design pattern for this. Sadly, I didn't find any.
If there is no pattern, how would you go about realizing this? Any input is greatly appreciated.
Your approach is what I've seen in most applications with this kind of capability. The only changing piece is that some places will put the "default" values into the base table (Entry) while others will treat it as just another Content row.
That design will also give you the ability to search (or restrict search) in all languages easily. From a db design perspective, its imho the best design you can use.
With small amounts of text and a simple application this would work. In the large, you might be bitten by the extra joins needed, especially when your database is larger than ram. Presenting things in the right order (sorting) also might need solving

How many database table columns are too many?

I've taken over development on a project that has a user table with over 30 columns. And the bad thing is that changes and additions to the columns keep happening.
This isn't right.
Should I push to have the extra fields moved into a second table as values and create a third table that stores those column names?
user
id
email
user_field
id
name
user_value
id
user_field_id
user_id
value
Do not go the key / value route. SQL isn't designed to handle it and it'll make getting actual data out of your database an exercise in self torture. (Examples: Indexes don't work well. Joins are lots of fun when you have to join just to get the data you're joining on. It goes on.)
As long as the data is normalized to a decent level you don't have too many columns.
EDIT: To be clear, there are some problems that can only be solved with the key / value route. "Too many columns" isn't one of them.
It's hard to say how many is too many. It's really very subjective. I think the question you should be asking is not, "Are there too many columns?", but, rather, "Do these columns belong here?" What I mean by that is if there are columns in your User table that aren't necessarily properties of the user, then they may not belong. For example, if you've got a bunch of columns that sum up the user's address, then maybe you pull those out into an Address table with an FK into User.
I would avoid using key/value tables if possible. It may seem like an easy way to make things extensible, but it's really just a pain in the long run. If you find that your schema is changing very consistently you may want to consider putting some kind of change control in place to vet changes to only those that are necessary, or move to another technology that better supports schema-less storage like NoSQL with MongoDB or CouchDB.
This is often known as EAV, and whether this is right for your database depends on a lot of factors:
http://en.wikipedia.org/wiki/Entity-attribute-value_model
http://karwin.blogspot.com/2009/05/eav-fail.html
http://www.slideshare.net/billkarwin/sql-antipatterns-strike-back
Too many columns is not really one of them.
Changes and additions to a table are not a bad thing if it means they accurately reflect changes in your business requirements.
If the changes and additons are continual then perhaps you need to sit down and do a better job of defining the requirements. Now I can't say if 30 columns is toomany becasue it depends on how wide they are and whether thay are something that shouldbe moved to a related table. For instnce if you have fields like phone1, phone2, phone 3, youo have a mess that needs to be split out into a related table for user_phone. Or if all your columns are wide (and your overall table width is wider than the pages the databases stores data in) and some are not that frequently needed for your queries, they might be better in a related table that has a one-to-one relationship. I would probably not do this unless you have an actual performance problem though.
However, of all the possible choices, the EAV model you described is the worst one both from a maintainabilty and performance viewpoint. It is very hard to write decent queries against this model.
This really depends on what you're trying to do.

CREATE TABLE auto append default columns?

In MySQL, is it possible to append default columns after creation or create them automatically? A brief overview is this:
All tables must have 5 fields that are standardized across our databases (created_on, created_by, row_status etc). Its sometimes hard for developers to remember to do this and/or not done uniformly. Going forward we'd like to automate the task some how. Does anyone know if its possible to create some sort of internal mysql script that will automatically append a set of columns to a table?
After reading through some responses, I think i'd rephrase the question bit, rather than making it an autoamtic task (i.e EVERY Table), make it function that can be user-triggered to go through and check for said columns and if not add them. I'm pretty confident this is out of SQL's scope and would require a scripting language to do, not a huge issue but it had been preferable to keep things encapsulated within SQL.
I'm not very aware of MySQL specific data modeling tools, but there's no infrastructure to add columns to every table ever created in a database. Making this an automatic behavior would get messy too, when you think about situations where someone added the columns but there were typos. Or what if you have tables that are allowed to go against business practice (the columns you listed would typically be worthless on code tables)...
Development environments are difficult to control, but the best means of controlling this is by delegating the responsibility & permissions to as few people as possible. IE: There may be 5 developers, but only one of them can apply scripts to TEST/PROD/etc so it's their responsibility to review the table scripts for correctness.
i would say first - don't do that.
make an audit table seperately - and link with triggers.
otherwise, you will need to feed your table construction through a procedure or other application that will create what you want.
I'd first defer to Randy's answer - this info is probably better extracted elsewhere.
That said, if you're set on adding the columns, ALTER TABLE is probably what you're looking for. You might consider also including some extra logic to determine which columns are missing for each table.