I am writing a web app that takes user input from a series of forms (think "wizard") and stores it in a SQL database as the user progresses.
Let's say they are submitting an application form on behalf of a company that has an address. The application form will also have a list of supporting info.
So the simplified schema will have 4 tables (note that each table will have plenty of other fields to capture):
**ApplicationForm**
Id: PK
CompanyId: FK
**Company**
Id: PK
Address: FK
**Address**
Id: PK
**SupportingInfo**
Id: PK
ApplicationFormId: FK
A user first starts an application form, fills in some important details over a couple of screens, then adds the company details, then adds the company address, and finally adds the list of supporting info.
Given that I cannot create the entire data model in one insert, how do I go about saving the users' input as they progress through the web pages?
When I save the ApplicationForm, I will have a FK violation because there is no Company. When I create the Company, I will have a FK violation because the Address only gets saved later. (Supporting Info does not have this problem because it has a many-to-one relation and the FK will always be valid.)
I have thought of the following:
Do I disable constraint checks?
Or allow the FKs to be null?
Or create "dummy" entries in the related tables until the user enters their details?
Or create separate data models data entry and persistance)?
Or save "in progress" data as JSON or XML?
All the options have significant drawbacks, and the last two in particular seem like overkill for a simple user entry app.
I am working with Entity Framework and SQL Server if that makes any difference to the answers. (I realise that NoSQL may be a suggestion here, but I can't change the database.)
I am working on a bank application in which a customer can open multiple accounts for different product types like: Insurance, Investment and annuity etc.
Each customer has a profile and we are saving that information in 12 different tables such as : Personal,Contact,Address,Affiliation,Financial,Investment,Asset,Liability,NetWorth and so on.
Now to open each account we have to collect and save same kind of information like for customer profile but we cannot overwrite the customer profile with that as we have to keep track of each accounts information when its submitted to the point when it get opened.
So in terms of solution we think either to have replica of these 12 tables for each account or to save the JSON for each table in one table only which has 12 columns for each of above table and populate UI with that.
Can somebody if have prior experience suggest us how to do this in best way.
I would determine which information will not change between accounts. For example, name, birthday, ssn, etc. These constant fields can form a table called customers. If there are no constant fields, then you can use a placeholder id, which simply helps to associate accounts to the same user.
I would also create a table for Accounts and use the account_id as a foreign key for all your customer information that may change between accounts. Each row in the Accounts table will be owned by a customer from before.
So the relationship between customers and accounts would be one to many, and the relationship between accounts and "account specific customer info" would be one to one.
I have a table of users in SQL Server with all the contact details, personal details etc. When each user signs up to my website they will be given the option to opt-in to 5 different types of emails like:
I wish to receive emails about new things
I wish to receive the monthly newsletter
etc etc. I am trying to decide the best way to store this information in a database. My current thinking is to have a seperate table with 5 columns (one for each opt-in) and the value being a bool/bit value.
Since the information wont be required regularly, it will only be required when we want to send mail to user. Are there any better ways / best practices for doing something like this?
The problem with your proposed design is that it becomes difficult to add new email types in the future; you only have 5 now, but what happens when you add a sixth or seventh?.
Instead, I would propose something like:
User Table:
UserID (Primary Key)
User Attributes
EmailTemplate Table
EmailTemplateID (Primary key)
Email Template Attributes
UserEmailTemplates
UserID
EmailTemplateID
You can easily add new templates, and associate them with users.
I have a database with a "users" table containing data about my users. Each user is to be linked to a company or a college. I wish to have two separate tables "college" and "company" each with a field "ID". So how do I link each record in the users table to either a company or a college?
The basic thing is that I wish to establish an "OR" relationship in the database.
You can use subtype/super-type relationship. Keep all common fields in the organization table. College and company tables contain only fields specific to those entities.
You could use an 'institution' or 'organisation' lookup table, with a structure something like
InstitutionId[PK], InstitutionType, LookupKey
where LookupKey is the PK to either Company or College.
Or,
InstitutionId[PK], CompanyId[FK], CollegeId[FK]
In both cases you link from user to institution, then onto Company and/or College.
I personally prefer the second option, because it allows you to easily validate the FK relationship and also allows (if applicable) for a user to be a member of a company and/or a college.
I would create relationtables. UserCollege and UserCompany. This way you are even able to have users that are linked to both if needed in the future. If not you simply just create a relationrecord on one of the both
I have several entities which respresent different types of users who need to be able to log in to a particular system. Additionally, they have different types of information associated with them.
For example: a "general user", which has an e-mail address and "admin user", which has a workstation number (note that this a hypothetical case). Both entities also share common properties like first name, surname, address and telephone number. Finally, they naturally need to have a (unique) user name and a password to log in.
In the application, the user just has to fill in his user name and password, and the functionality of the application changes slightly according to the type of the user. You can imagine that the username needs to be unique for this work.
How should I model this effectively?
I can't just create two tables, because then I can't force a unique constaint on the user name.
I also can't put them all in just one table, because they have different types of specific information associated to them.
I think I might need 3 seperate tables, one for "users" (with user name and password), one for the "general users" and another one for the "admin users", but how would the relations between these work? Or is there another solution?
(By the way, the target DBMS is MySQL, so I don't think generalization is supported in the database system itself).
Your 3 tables approach seems Ok.
In users table have only ID, username, password,usertype.
In general users table have ID, UserID (from users table), other fields.
Same thing for admin users.
Usertype field will tell you from what table to search for additional info
if(usertype==admin)
select * from admins where userid=:id;
else
select * from general where userid=:id;
Two tables. USERS with user names, first, last, etc. ROLES with roles, and a link back to the user name (or user id or whatever). Put a unique constraint on the user name. Put workstation nbr, email, phone, whatever else you need, in the user table. Put 2 columns in the ROLES table -- USERID and ROLE.
You should decide how much specific information is being stored (or likely to be stored in the future) and make the decision based on that. If there are only a handful of fields for each user type then using a single table is alright.
USERS table (name, type, email, password, genfield1, genfield2, adminfield1, adminfield2)
Make sure to include the type (don't assume because some of the fields particular to that user are filled in that the user is of that type) field. Any queries will just need to include the "AND usertype = " clause.
If there are many fields or rules associated with each type then your idea of three tables is the best.
USERS table (ID, type, name, password)
GENUSERS (ID, genfield1, genfield2)
ADMINUSERS(ID, adminfield1, adminfield2)
The constraints between IDs on the table are all you need (and the main USERS table keeps the IDs unique). Works very well in most situations but reports that include both types of users with their specific fields have to be done in two parts (unioned SQL or subqueries or multiple left joins).
You can solve it with one 'general' users table containing the information thats available for all users and 1 table for every specific user type. In your example you will then need 3 tables.
Users: This table holds only information shared between all usertypes, ie. UserId, Name, Address, etc.
GeneralUsers: This table 'extends' the Users table by providing a foreing key UserId that references the Users table. In addition, information specific to general users are held here, fx. EmailAddress, etc.
AdminUsers: As with GeneralUsers, this table also 'extends' the Users table by providing a foreign key UserId referencing the Users table. In addition information specific to admin users are held here, fx. WorkstationId, etc.
With this approach you can add additional 'specializations' if the need arises by simply adding new tables that 'extends' the Users table using a foreign key reference. You can also create several levels of specialization. If for example admin users are general users as well as admin users then AdminUsers could 'extend' GeneralUsers instead of Users simply by using a foreing key to GeneralUsers instead of Users.
When you need to retreive data from this model you need to which type of user to query. If for example you need to query a GeneralUser you will need something similar to:
SELECT * FROM GeneralUsers
LEFT JOIN Users ON GeneralUsers.UserId = Users.UserId
Or if querying an admin user
SELECT * FROM AdminUsers
LEFT JOIN Users ON AdminUsers.UserId = Users.UserId
If you have additional levels of specialization, for example by having admin users also being general users you just join your way back.
SELECT * FROM AdminUsers
LEFT JOIN GeneralUsers ON AdminUsers.UserId = GeneralUsers.UserId
LEFT JOIN Users ON GeneralUsers.UsersId = Users.UserId
I most definitely would not do a model where you have separate tables as in GeneralUser, AdminUser and ReadOnlyUser.
In database design, a good rule of thumb is "Down beats across". Instead of multiple tables (one for each type), I would create a SystemUsers table, and a Roles table and define a join table to put SystemUsers in Roles. Also, I would define individual roles.
This way, a user can be added to and removed from multiple roles.
A role can have multiple permissions, which can be modified at any time.
Joins to other places do not need a GeneralUserId, AdminUserId and ReadOnlyUserId column - just a SystemUserId column.
This is very similar to the ASP.Net role based security model.
alt text http://img52.imageshack.us/img52/2861/rolebasedsecurity.jpg