views:

91

answers:

2

I have different 3 types of users and each type of user can have columns and relationships with tables that another type doesn't, but all of them have login(Unique) and password,
how would you do:

  • create a table for each type or
  • create one table for all of them or
  • create a table for all of them only for login and password and separate for all the other things and bind them with a FK
  • something else
+10  A: 

Number 3 is the best of the options you suggested (updated slightly for clarification):

  • create a table for all of them for login and password and anything else that is shared and a separate table for all the other things that are not shared and bind them with a FK

Except don't store the password, store a hashed version of a salted password.

An alternative might be to assign groups and/or roles to your users. This might be more flexible than a fixed table structure, allowing you to add new roles dynamically. But it depends on your needs whether this is useful for you or not.

As Aaronaught pointed out, in the main table you need an AccountType to ensure that a user can only have one of the roles. You must remember to check the value of this column when joining the tables to ensure that a user has only one role active.

A unique constraint on the foreign key ensures that a user can only have a role once.

Mark Byers
one thing with this option is that there is no constraint to stop two rows from 2 different user types tables to reference the same row in in the "login_password" table
Omu
@Omu: Put a `UNIQUE` constraint on that column in each FK table, and use a discriminator column (`AccountType`) in the main table. You should have the discriminator anyway, it's critical for efficiency (and Mark, I think you should add this).
Aaronaught
@Aaronaught: Good point. When I originally posted my answer wasn't clear that each user could only have one role, but I can see that now from Omu's comments.
Mark Byers
@Aaronaught could you explain that, if i have this schema: Account(AccountID, login, password, UserType(this is char cuz i need to know the usertype for this account)) UserType1(id, AccountID, ...) UserType2(id, AccountID,...) how do you do what you said ?
Omu
how is the AccountType in the main table going to prevent a user from having multiple roles ? this doesn't create a constraint
Omu
@Omu: Excellent question! The answer is perhaps not obvious, so I'll put this into my post: When you join, check the account type as part of the join condition. Don't just check if the user exists in the table.
Mark Byers
so the Unique key constraint on each column AccountID FK from the UserTypes Tables ensures that a UserType can reference one Account and the join condition will help to obtain zero rows from the UserTypes table which is not of the specified AccountType, but it is still possible to insert ONE row in each UserType table that is going to reference same row in Account table, although if we write the join with the AccountType condition we aren't going to get the bad data from the DB
Omu
Omu: Yes, you can insert the row but it will never be fetched if the AccountType is incorrect.
Mark Byers
I did it like this: http://consultingblogs.emc.com/davidportas/archive/2007/01/08/Distributed-Keys-and-Disjoint-Subtypes.aspx
Omu
+2  A: 

I had this exact question when building a recent system. Here's a thread that was super-helpful for me: http://stackoverflow.com/questions/600684/object-oriented-like-structures-in-relational-databases.

I went with the disjoint subtypes solution, described well here: http://stackoverflow.com/questions/561576/polymorphism-in-sql-database-tables/561960#561960

Alex
I see, that solution, is the perfect one from the constraints point of view, but I think it's going to be slower and I'm going to have more trouble with all those compound FK
Omu
noup :), it's actually better, I need my DB consistent
Omu