views:

52

answers:

3

In my application users can be one of three types: teens, individuals, or members of an organization. In my users table, I have a boolean field teen (not null) and a foreign key organization_id (null).

If teen is true and organization_id is null, the user is a teen. Teens can't belong to an organization.
If teen is false and organization_id is null, the user is an individual.
If teen is false and organization_id is not null the the users is a member of an organization.

There has to be a better way of doing this. I don't like that the case exists where teen is true and organization_id is not null.

Would it be better to add a new table, organizations_users, and remove the organization_id foreign key from the users table? The downside I see to that is that it will take me longer to determine whether or not a user is an individual or an organization, and fetch the data if appropriate.

Is there a more elegant way of handling this?

+2  A: 

It would simplify your code if you had a role column that had either teen, individual, or member. You'd probably normalize these roles to their own table, and use a foreign key:

Roles
1      Teen
2      Individual
3      Member of an Organization
Marcus Adams
+1 - better than my answer and it leaves room for new user types in the future.
JNK
How would I then look up data in the organization table if I determined the user was a member of an organization?
birderic
@birderic, the lookup wouldn't change. You'll still store the organizational data for members. There is some minor redundancy if you consider the fact that you can calculate some of these values, but that redundancy simplifies your design and code and at the same time builds in flexibility. By the way, if people start being able to have multiple roles, you turn the relationship between User and Roles to one to many with another table.
Marcus Adams
@marcus I understand that, but would I keep the foreign key in the users table or place it in the roles table? In the second case, there would then be a lot of null fields.
birderic
In the first case, put a Role column in the Users table, and store the key to the Role table. If a User is a Teen, then you would store 1 in the Role column. In the second case, you would not have a Role column in the User table. You would have a UserRoles table, where column one would be UserID and column two would be RoleID.
Marcus Adams
I understand the relationships, I'm just confused as to where the foreign key to the organization table would go. Would it stay in table users?
birderic
Yes, I think that the key for organizations would stay in Users.
Marcus Adams
A: 

Use 2 tables. Table 1 is a User table which contains user information. It also contains a foreign key to the ID of the next table.

Table 2 is UserType. The id is an identity. This contains'Teen', 'Individual' and 'Organization'.

To do a lookup, simply do a join.

asp316
+1  A: 

Seems to me that you have cornered yourself with this design. In general, it is better to keep your abstractions (models) in sync with the real world, as opposed to some very special case. For example, a teen is a person between ages 13 and 19 (depends on definition). A teen can be a member of a swimming club, which is an organization. A person of any age may or may not be a member of an organization. I would suggest the following:

alt text

Damir Sudarevic
In my case teens cannot belong to organizations (and will never have that ability). Are you saying its better to allow it but forcefully program around it?
birderic
Yes, allow your model to follow the usual abstraction -- the one already wired-in most human brains. In your example, a person who happens to be teen will simply not have an entry in the Membership table.
Damir Sudarevic