Multiple Role Database Design - sql

I recently had this problem in designing a SQL database.
I want to create a database for a school, and of course not all users have the same role or privileges.
For example, there are teachers, headteacher, students and parents.
If I put all those in the same table and put a role column the table, then I can't be free to put any other columns for a specific role
like I can't add a grade column for student because the other roles don't have grades.
Also I can't put them in separate tables because in the log in I can't specify the role for this user and go to his table .
What is the best way to do something like this?

Use polymorphism on the user table.
Create a user table with basic authentication and common information like email and credentials. Now create 2 columns authority_type, authority_id (naming can be changed).
Now for every type of new role or privilege, create a table.
For e.g. In your case, there will be a table for the teacher, headteacher, student and parent. All have separate sets of attributes.
Whenever saving a user record, you'll use its authority_type and its authoriy_id ( record foreign key of that other table ).

Related

Foreign key or boolean value in database

Let's say I have a database with two tables, User and Store.
Lets make the rules:
A User must belong to one Store
A Store may have one or more Users
A store though, may have a store manager. What is the best approach for this?
Adding a 'is_store_manager' boolean column at the Users table, or create a foreign key called something like manager_user_fk at the Store table? I guess that would create a many to many relationship though, which would be bad, but it would be a solid constraint to select a user I think. What would be the best approach?
Don't create a fk on the Store. It is somewhat redundant and will make some future SQL queries harder.
You could add another table, UserType with the Manager, and Non-Manager types. You'd then add a fk on the Users table pointing to the UserType.
Edit:
If you wanted a user to be allowed multiple roles, you'd need another join table:
Let's call the previous table table Role, instead of UserType, and add another table, UserRole that is a join between User and Role (it has only 2 columns: a foreign key to User, and a foreign key to Role. With this setup, you wouldn't have any fk on the User table, as this join table would hold all the information about the relationship. A user could have as many roles as you like then.
An alternative to the accepted solution which only allows a user to be of one type you can use what I've been doing to replace boolean status fields. Create a table called UserManager with a primary key also being a foreign key to User.
Any user with an entry in UserManager is a manager. To get the managers you just join the User table with the UserManager. This also lets you store more meta data (i.e. you could store when the user became a manager etc).
Then if you want an AdminUser table, you do the same thing. Any user in the AdminUser table is also an admin. You can have a user be both (or none, or one). Along with storing more meta data about the type.

1 to 1 database design

I have a database and normally users are the central object.
In database I have a tables roles and users in roles so I can give users different permissions on site.
But now I have one doubt.
I saw before one database with structure like this (User is in 1:1 relation to other tables):
User{UserId, Username, Email etc.}
Admin{UserId, some specific columns}
Child{UserId, some specific columns}
Admin{Parent, some specific columns}
and other tables are connected to user not through User table but through Admin, Child and admin.
Because now I design my database I have Users and user can be Admin, CompanyManager and Professor.
I wonder should I design table like I show above or just relied on roles?
What is advantage of the first approach?
And also in my business model User doesn't have to be CompanyManager or Professor so this is actually 1 to 0 or 1 design.
What is a good way to design database with scenario like this?
The advantage of having specific tables for certain types of users is to store information that is only relevant to that class of user.
In your example,
perhaps all users would have a manager - so the manager ID would go in the users column.
managers would have permissions to view certain information, so this would be handled via a role.
only professors would have a Subject, or the "HasTenure" property. So this information would go in a professors table. Using this approach, you avoid the need to have a "Subject" column in the users table, when it is only applicable to a certain subset of users. As such you avoid a functional dependency in the users table, and a violation of 3rd Normal Form.
I prefer this approach:
In this way, you can easily group Roles into categories and assign them to users.

Database design relations in User and Profile

I'm designing a web application for a school. So far, I'm stuck with the database which has these tables:
users
id
username
password
profile
user_id (FK)
name
last_name
sex
group_id (FK)
(other basic information)
... And other tables irrelevant now, like events, comitees, groups and so on.
So, the users table stores basic information about the login, and the profiles table stores all the personal data about the user.
Now, the *group_id* column in the profile table has a foreign key that references the ID column of the group in which the user is currently enrolled, in the groups table. A user can only be enrolled in one group at once, so there's no need for any additional tables.
The thing is that it doesn't make much sense to me declaring a relation like group HAS MANY profiles. Instead, the relation should be group HAS MANY users, but then, I would have to put a *group_id* column on the users table, which doesn't really fit in, since the users table only stores auth information.
On the other side, I would like to list all the users enrolled in a group using an ORM and getting the a users collection and not profiles. The way I see it, is that the users table is like the 'parent' and the profiles table extends the users table.
The same problem would occur when setting attendances for events. Should I reference the profile as a foreign key in the events_attendance table? Or should I reference the user ID?
Of course both solutions could be implemented and work, but which of them is the best choice?
I have dug a little and found that both solutions would comply with 3NF, so in theory, would be correct, but I'm having a hard time designing the right way my database.
This is a question of your own conventions. You need to decide what is the main entity, right after that you can easiy find a proper solution. Both ways are good, but if you think of User as of the main entity while Profile is a property then you should put GroupId into User, otherwise, if you mean User and Profile as a single entity, you can leave GroupId in Profile, and by this you're not saying group HAS MANY profiles but group HAS MANY users.
By setting a proper one-to-one relation (User-Profile) you can force your data integrity good enough.

Do I need a login table?

Hey guys I have a simple database question. Say I am emulating a university login system.
If i have a student table and faculty table, can I just store the password directly in the corresponding table? For example student table has such attributes as (student_ID - primary key), First_name, Last_name, Classification, and now I would add a password field.
If I create a login table i'm just effectively copying over thousands of potential records. Is there any benefit to creating a login table with say (primary key STUDENT_ID,FACULTY_ID) and a password field for authentication purposes?
Can I increase security on just one table? What is the better approach?
As one student contains only one password, there maintains one to one relationship so there is no need of splitting the table for one to one relationship.
If there is one to many relation, breaking the table will be good such as for storing multiple phone numbers or multiple address of a user.....
You need to decide upon whether only students will be allowed to login into your system.
What about admin user, teachers, etc?
even if there is a remote possibility that a non student will log into the system it is advisable to create a login table with userid and password stored in MD5 encryption

use of views for validation of an incorrect login-id or an unidentified user

I read this on msdn:
Views let different users to see data in different ways, even when they are using the same
data at the same time. This is especially useful when users who have many different interests and skill levels share the same database.
For example, a view can be created that retrieves only the data for the customers with whom an account manager deals. The view can determine which data to retrieve based on the login ID of the account manager who uses the view.
My question:
For the above example , i would have to have a column named Userid/LoginId on my table on which the view is created so that i can apply a check option in the view for this column. and then if a user with a name not in that column tries to enter data , then he/she is blocked.
Yes, you are right. You should
add a column with the user's login or database user name (say you call it username),
each row should have username populated with the login or database name of the person who is allowed to see that row
you can then build a view where you use the builtin functions SUSER_SNAME() (for logins) or USER_NAME (for database names) in your WHERE clause to filter only the rows the user is allowed to see
See Granting Row-Level Permissions in SQL Server (ADO.NET).
You don't have to add a column to the table: it could be more appropriate to instead add a new table to model the relationship.
There's a deisgn rule of thumb that states a table should model an entity or a relationship but not both. Let's say the table in question models the companies a customer owns (i.e. an entity table) and the business rule states the the account manager can only see companies relating to customers he looks after.
Is account manager an attribute of a company? No, so account_manager should not be a column (attribute) in the Companies table.
Is there a direct relationship between account_manager and a company? No, so a relationship table between is not due here (because the relationship is indirect).
Rather, the direct relationships are between account manager and customer, and between customer and company respectively. There should be two tables whose sole purpose is to model these relationships.