I have table like below.
I want to store user roles like admin,reader,writer
How can I store the values in my table.
I searched in google and many results such as 2 types.
Storing values to a single column name as user_roles and store values with pipe (|) separated (same as above).
Storing values on another table like user_roles and store with foreign key of users.
Which of the above two method is better for development ?
Tell me the advantage and dis-advantage of both please...
Thanks & Regards
The reasons you want the second choice include, mainly
Data Normalization Sanity
Speedy use of indexes and not table scans
Avoiding coding nightmares like find_in_set()
See Junction Tables or associations tables (more simplified)
See Nightmare Coding without it (and slow performance as all get up).
If you user is having more than one user roles, so definitely it will define as one to many relationship.
So adding table with permutations alone with user Id is best option. Cz one user can have many user roles.
this kind of combination never happens (one-to-one)
user A - admin
User B - writer
User C - reader
Possible is (one-to-many) or (many-to-one)
User A- Admin + reader
User B - reader + writer
user C - Admin + reader + writer
user D - Admin + writer
.....
as well as read these too
One to Many and Many to One Relationships - code.tutsplus.com
One-to-many relationship - www.databaseprimer.com/
Database Normalization
Related
I am building a PHP app that has 3 basic entity types: Coach, Student, Lesson, where coaches create digital lessons for students. I'm using MySQL and innoDB tables.
Requirements
Coach and student login.
Coach can deliver a digital lesson specifically for a single student.
I'm unsure what is the best DB schema to use given the requirements. Here are two options:
Option 1
User (PK id, user_type (coach or student), firstname, lastname, email, password, etc...)
Lesson (PK id, FK coach_user_id (ref: User.id), FK student_user_id (ref: User.id), lesson_name, etc…)
Pros:
- One user table
- Each user has a unique ID and email
- Makes login auth easy with single table
Cons:
- No validation of user_type when a coach or student User.id is recorded as a FK in the lesson table. This problem will reoccur in any new table where a coach or student User.id needs to be recorded as a FK.
- Potential polymorphism issues and the need to normalise down the track.
Option 2
Coach (PK id, firstname, lastname, email, password, etc...)
Student (PK id, firstname, lastname, email, password, etc...)
Lesson (PK id, FK coach_id (ref: Coach.id), FK student_id (ref: Student.id), lesson_name, lesson_text, etc…)
Pros:
- Normalised DB schema. Independent coach, students entity tables.
- No user type validation issues. Coach ID and student ID FK's point independently to Coach.id and Student.id respectively.
Cons:
- Coach and student can have the same ID. (This can be solved though with ID prefixes e.g. C1001, S1001)
- Coach and student can have the same email.
- Login auth involves querying two 2 tables for single login page, or creating 2 different login pages and auth request types.
I'm really torn which is the best way to go. Is there a better way to do this?
In my opinion, both of your approaches would work. The first one is more universal, and capable of fitting various currently unknown requirements . If you choose it, I'd recommend to add concept of Role to the model - "user_type" is a role, and one user can be associated with different roles [at the same time]. Also, "The Data Model Resource Book" by Len Silverston is a great resource .
However, you may not always want your schema to be too general. You listed pros and cons for 2 approaches on very low level; I think that practicability is more important than particular technical issues (which can be overcome ). I'd put it that way :
1) Pros :
easy to accommodate new features without major changes to schema
very flexible
easy to build cubes on top of the schema
fits long term projects
Cons :
requires more resources (experienced DBA/Data Model specialist[s], comparatively longer design time )
way more complex than (2)
2) Pros :
fast delivery of first working version
quite easy for understanding even by non-technical people (until it grows up)
fits either small projects or projects with well-defined domains which [almost] never change
Cons :
never ending refactoring of schema as new requirements come
if project lives long enough, database becomes full of "not used anymore" columns(or other db objects) nobody wants to touch
harder to enforce integrity
I hope it makes sense and helps you to make the right decision which fits your needs.
Option 1 looks better to me.
It will simplify your code when you don't care to distinguish students from coaches, and will be pretty much the same as option 2 if you want to distinguish them.
If you really need to validate the foreign keys you can use triggers to check if its a coach or not.
I'm not sure what you mean by "Potential polymorphism issues and the need to normalise down the track.".
I am trying to model a database for my current project and I came across a new problem. I have a Project which is supervised by Supervisor, Coordinator and Company. So Project table has Supervisor.id as foreign key and so on. There is also Student table which contains Project.is as a foreign key (because many users can do a project). This is how it is right now. What I would like to do is to have a User table containing a column named type which allows me to see what the role of that particular user is (also student). Even though the table will contain many NULL entries, I will have far less redundant code.
However, the main reason I want to have one User table is that I am using CakePHP and it is not easy to have different models log in. Is this possible in a nice way?
Thanks
EDIT: Maybe I should say that every one of these roles will have different permissions.
I see three tables: USER, GROUP, and ROLE.
Users would be assigned to groups, and groups given roles. I think you need three, not one.
And cardinality matters: I can see where a USER could be assigned to many GROUPS; a GROUP could have many USERS; a ROLE could be assigned to several GROUPS; and a GROUP could have many ROLES. There are many to many JOIN tables as well:
USER <-> USER_GROUP <-> GROUP <-> GROUP_ROLE <-> ROLE
This is normalized - nothing is repeated this way. USER, GROUP, and ROLE have primary keys. The JOIN table primary key is a composite of the two IDs in each row.
It depend on how you will use your associations.
Why not
For example: if you use relation to output data later and you sure, that you database scheme will not changed, than ... why not? your main targets: quality of code and speed of development, so, not matter how much columns with null you will have.
But
if you not sure in your requirements or plan to extend database scheme you can use two columns
supervisor_model
supervisor_id
which will store apropriate values: Company, 77 (I mean that 77 it's id of come Company )
Another approach
You can UUID for you supervisor_id so, it will be unique among several tables and you have not many NULL and extra columns.
I've done quit a bit of programming with php/mysql on small scale personal projects. However I'm working on my first commercial app that is going to allow customers or businesses to log in and perform CRUD operations. I feel like a total noob asking this question but I have never had to do this before and cannot find any relevant information on the net.
Basically, I've created this app and have a role based system set up on my data base. The problem that I'm running into is how to separate and fetch data for the relevant businesses or groups.
I can't, for example, set my queries up like this: get all records from example table where user id = user id, because that will only return data for that user and not all of the other users that are related to that business. I need a way to get all records that where created by users of a particular business.
I'm thinking that maybe the business should have an id and I should form my queries like this: get all records from example where business id = business id. But I'm not even sure if that's a good approach.
Is there a best practice or a convention for this sort data storing/fetching and grouping?
Note:Security is a huge issue here because I'm storing legal data.
Also, I'm using the latest version of laravel 4 if that's any relevance.
I would like to hear peoples thoughts on this that have encountered this sort problem before and how they designed there database and queries to only get and store data related to that particular business.
Edit: I like to read and learn but cannot find any useful information on this topic - maybe I'm not using the correct search terms. So If you know of any good links pertaining to this topic, please post them too.
If I understand correctly, a business is defined within your system as a "group of users", and your whole system references data belonging to users as opposed to data belonging to a business. You are looking to reference data that belongs to all users who belong to a particular business. In this case, the best and most extensible way to do this would be to create two more tables to contain businesses and business-user relations.
For example, consider you have the following tables:
business => Defines a business entity
id (primary)
name
Entry: id=4, name=CompanyCorp
user => Defines each user in the system
id (primary)
name
Entry: id=1, name=Geoff
Entry: id=2, name=Jane
business_user => Links a user to a particular business
user_id (primary)
business_id (primary)
Entry: user_id=1, business_id=4
Entry: user_id=2, business_id=4
Basically, the business_user table defines relationships. For example, Geoff is related to CompanyCorp, so a row exists in the table that matches their id's together. This is called a relational database model, and is an important concept to understand in the world of database development. You can even allow a user to belong to multiple different companies.
To find all the names of users and their company's name, where their company's id = 4...
SELECT `user`.`name` as `username`, `business`.`name` as `businessname` FROM `business_user` LEFT JOIN `user` ON (`user`.`id` = `business_user`.`user_id`) LEFT JOIN `business` ON (`business`.`id` = `business_user`.`business_id`) WHERE `business_user`.`business_id` = 4;
Results would be:
username businessname
-> Geoff CompanyCorp
-> Jane CompanyCorp
I hope this helps!
===============================================================
Addendum regarding "cases" per your response in the comments.
You could create a new table for cases and then reference both business and user ids on separate columns in there, as the case would belong to both a user and a business, if that's all the functionality that you need.
Suppose though, exploring the idea of relational databases further, that you wanted multiple users to be assigned to a case, but you wanted one user to be elected as the "group leader", you could approach the problem as follows:
Create a table "case" to store the cases
Create a table "user_case" to store case-user relationships, just like in the business_user table.
Define the user_case table as follows:
user_case => Defines a user -> case relationship
user_id (primary)
case_id (primary)
role
Entry: user_id=1, case_id=1, role="leader"
Entry: user_id=2, case_id=1, role="subordinate"
You could even go further and define a table with definitions on what roles users can assume. Then, you might even change the user_case table to use a role_id instead which joins data from yet another role table.
It may sound like an ever-deepening schema of very small tables, but note that we've added an extra column to the user_case relational table. The bigger your application grows, the more your tables will grow laterally with more columns. Trust me, you do eventually stop adding new tables just for the sake of defining relations.
To give a brief example of how flexible this can be, with a role table, you could figure out all the roles that a given user (where user_id = 6) has by using a relatively short query like:
SELECT `role`.`name` FROM `role` RIGHT JOIN `user_case` ON (`user_case`.`role_id` = `role`.`id`) WHERE `user_case`.`user_id` = 6;
If you need more examples, please feel free to keep commenting.
Let us say I have two different entities on a site.
Teachers and Students.
They both login to the website.Right now I have the following tables
**Users**
- id
- email
- password
**Students**
- GPA
- SAT
- ACT
- user_id references Users ID
**Teachers**
- user_id references Users ID
- classroom_no
- salary
- average_class_size
So when a Student registers I add a row in both the Users and Teacher table.
When a Teacher registers, I add a row in both the Users and Teacher table.
Is it better to just have ONE table Users with the following fields?
**Users:**
- id
- ACT
- GPA
- SAT
- average_class_size
- salary
- classroom_no
- role (0 = teacher 1 = student)
even though some rows would refer to teachers (and thus not use the ACT, SAT, GPA fields)
??
Thanks!
If you are not familiar with database normalization, please read this.
Unless performance is a serious issue, I would not look at using a single table for this structure. As your project goes one, you will more than likely add more fields to each role and possibly add more roles as well. It will become increasingly more difficult to maintain this.
I would actually go a step further and introduce another concept called role into your application, along with the appropriate data model to persist it.
Your tables should be:
users:
- id
- email
- password
roles:
- id
- type
user_roles:
- user_id
- role_id
role_teacher:
- user_id
- classroom_no
- salary
- average_class_size
role_student:
- user_id
- GPA
- SAT
- ACT
Having a separate role table will let you separate your authentication table (users) from the rest of the data. This might become important if a user can be both a teacher and a student.
This should give you a basic understanding of how to structure your database.
You may find that you will begin to model some of the other concepts like classes in your system. So adding the appropriate tables may look something like:
role_teacher:
- user_id
- salary
classroom:
- id
- capacity
class:
- id
- name
- teacher_id
- classroom_id
- start_date
- end_date
class_enrollment:
- class_id
- student_id
- enrollment_date
- grade
Items like the teachers class room now moves to the class, allowing for the teacher to teach multiple classes (maybe you need to re-add the concept of "home room"). The teachers average class size then just becomes a calculation (though you may want to still store it for the sake of efficiency).
Hope this helps guide you in the right direction!
You should to go with Teachers and Students tables. Tables in database should reflect real world model (whenever it's possible of course). Merging everything into single User table brings very little value and introduces following issues:
redundancy (teacher doesn't need ACT, GPA and so forth fields as you mentioned)
complexity (you'll need extra logic to determine whether user is student or teacher)
ambiguity (is user a system user, or real world person data, or just login information...?), term is far too generic
On top of that, I'd rename Users table to UserLogins - it indicates its purpose more clearly.
My feeling is that it's better the way you have it - you have to maintain both tables so that they're in sync, but you've better encapsulated the role of "User", "Student", and "Teacher" this way. It also leaves you a better maintenance footprint - what if you want to allow a "Parent" to log in with a reference to their child? What about a "Principal"? These are all users, but would quickly gum up the unified table.
There are a couple of ways to do this, but I think one table for users is the right way to go. You could have the empty columns - it doesn't look the greatest, but if it works for you, it would allow minimal coding to get the values you need.
Another option might be to have an attributes table { UserId, Attribute, Value }, then for example, you could have: User1 GMAT 710, User1 ACT 30, etc. So you could then get a list of all attributes for a user by select * from attributes where UserId = user.UserId or some such. More code overhead, much cleaner. This would also allow you to add more attributes in the future for whatever purpose, and keep your database the same.
If one teacher can take multiple classes, then your design fails, as the teacher table will have a multiple entries..
Instead Create one Teacher Table where we can store Teacher Table, create one intermedite table, where we can store the Teacher and His classes.
Similarly, Teacher and User table should be separate..
Let a separate User Table exists where we can store the Use details..
I have three different users tables, and I would like to know what is the best way to create a private messaging system for them to communicate.
I tried to create it with a simple db scheme:
id (int)
from (int)
to (int)
subject (varchar)
message (text)
timestamp (timestamp)
read (bool)
deleted_to (bool)
deleted_from (bool)
But complications instantly arised because of the three users tables, where user IDs in table A can have ID = 1 and another user in table B can have ID = 2
Any ideas on how to create a better DB scheme? Thanks
use "model" column with varchar type to save which user model the user comes from.
this way you can have several entries with "2" for example. model + user_id then has to be unique.
e.g.:
User1 3
User1 5
User2 3
...
A hackish solution would be to create a hash for every user and store it in one table to uniquely identify any users. Then, using the hashes, figure out which message was sent to which user.
It most certainly is not a great idea, because it generates unnecessary overhead sending several queries to the database. If possible, create a table to hold all users and using one-to-one relationships create tables for entity specific fields. Your authentication methods would be stored in the user table. Post authentication your system would know, which tables to join together for the required data as described in that single user table.
You could add two fields in your table to store the "table" related to the from and to.
Dunno what kind of db you are using but this problem could be solved easily with table inheritance.