I'm designing a MySQL database with some tables for a clinic and I need three different user types: admin, medic and patient.
What I did was to create a table called users where its columns are precisely the common fields shared by admins, medics and patients (there is of course a primary key called id_user which auto increments every time a user is added).
Then I created three tables regarding the specific data for each user type: admin, medic and patient in which I have a field called id_user which is a foreign key to id_user in the table users.
When I tried to establish the foreign key constraint for the three user type tables, phpMyAdmin doesn't allow me to set ON DELETE as "SET NULL" (I think that would make sense because if I delete a user from the users table then it should automatically set the fields as NULL in the medic, admin or patient tables, right?) and gives me the error "relation has not been added".
Doubt 1: What's happening here that I'm not aware of?
Doubt 2: Should I forget this way of relating tables and simply add the specific fields for each user type in the users table although some users will have some fields set as NULL?
Here is an image illustrating my database:
You should use Cascading Deletes instead of setting fields null, if you delete a user you want them gone if you null out the data you'll just have tables filled with nulls.
Also from what i understand you created 3 tables for each of the permission levels if this is the case you should maybe handle that in code with conditions checking the permissions level
Related
I've almost completed my very complex project, then realized I had one issue still hanging me up. How do you (or is it even possible) to have the foreign key auto update (to reflect the parent) for each child table?
I guess I should mention the main site is built through Joomla. Everything I will be referring to in this post resides outside of Joomla but on the same domain, with the exception to the user profiles.
For instance...
I have table dataCompany that stores the company information. This table will be a child table to the userProfile table. Now, userProfile table has an auto-incremented column (user_id) and I created a column by the same name in dataCompany (but not auto-incremented). I want the user_id in dataCompany to auto fill to match that from userProfile.
The user will be logged in when entering data into dataCompany, which I thought would make it easier to autofill the user_id foreign constraint. However, I still get the invalid error.
Perhaps I'm missing something, but I was under the impression foreign keys were the only way to hold separate tables together.
EDIT:
I'm pretty sure I didn't explain what I'm doing very well.... so here's another try.
I have a website. The user will sign up for said website. That creates user_id in mysql database. I have a form the user will fill out, and the information will be stored in dataCompany. This table has primary key of companyID but also has column user_id. I want the data the user inserts into dataCompany to be associated with the user data tied together by user_id. Now, when the user signs up the user_id is auto-incremented. I can't have the user putting in their user_id when filling out their company information (as they don't know what it is)... that's where the 'auto update foreign key' comes from. I just want it to replicate what is already in the parent table (userData).
This seems like a desirable feature but I can't seem to figure out how I would do it while the foreign key is a part of the primary key (composite key).
The table is a simple junction table for a many to many relationship referencing User.id and Access.id referencing functions a user has access to:
Column | References
user user.id
access access.id
Therefore there can be many entries for each user and each access level. To simplify things for "superusers" I wanted to have a NULL value for access which would mean they have access to every page (this is the only way I could figure how to enter a value that didn't reference a row in the access table). The problem is MySQL won't allow a NULL value as a part of the primary key.
Is there a way around the NULL issue with primary keys or is there another way to reference every row (or no rows) in a foreign key? The only other way around this I can think of would be to disable the foreign key or have to add a row for every access.id in the table. Either of which would be undesirable.
Presumably you have a superuser flag on your user table. You could UNION a Cartesian join of each superuser and the set of available access IDs into whatever query you need this for.
Depending on what you're doing, you could also just not store the access for a superuser in the database and treat them differently in code - i.e. ignore the access check once you've established them as SU. Depends on your application though.
I think NULL is allowed and you can use it as a unique combination along with user.id. But I am not sure if this is a good way to do this. I mean you can store the super user setting in a column and use it in the code than here.
How can we represent a relation where there is no need to add a foreign key in the table in DBDesigner? For Example, If i have 2 Tables As:
1) Admin
2) Machine
Suppose the relation "Admin can Add machines",
there is no need of Admin table's primary key to go in Machine's table as foreign key. Or you can say that i don't want to add it. But still i want to show this relation in my ERD. How can i do it using DBDesigner?
The best way is to create separate table Permissions.
Then there will be a row with specific permission Add machines
This way you can assign different permissions to different users.
Obviously you will need 2 more tables for this to work: Users where the user data is kept and say user_permissions with 2 fields only user_id & permission_id where you keep the info which user has which permission.
This is the right way to design scalable permissions that can expand and accommodate any set of permissions.
I have created 2 separate tables for admins and users in my database. I want to save user and admin login details (ip address, user_agent, connection time etc) into one table. Is the only solution to create two fields one for admin ids and other for user ids in this table (like below)?
CREATE TABLE login_detail (
id int NOT NULL AUTO_INCREMENT,
admin_id int,
user_id int,
ip_address ...
...
PRIMARY KEY (id),
FOREIGN KEY (admin_id) REFERENCES admin(id) ON DELETE RESTRICT ON UPDATE RESTRICT,
FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE RESTRICT ON UPDATE RESTRICT
)
If an administrator logs in, his id will be stored in admin_id and user_id will be empty. If a user logs in, his id will be stored in user_id and admin_id will be empty. What do you suggest (generally)?
I believe that ermagana understood you were converting those two tables into one table, not accessing those two tables through the new, third table. At least, that is what I assumed until I saw your response. Am I correct? If so...
In general, there is really no reason why this wouldn't all be in one table with a bit-flag indicating admin authority, as ermagana responded. I believe that would be the most common implementation, though certainly not the only option.
Your implementation using three tables, as I understand it, will require extra coding and certainly more database activity. You will need to check if the user is a user and, if not, then check if the user is an admin. Also, how are you going to ensure that the same user isn't in both tables without extra coding and database activity? At least how I understand it, it appears inefficient and error-prone.
Perhaps I don't understand it at all. If so, please clarify.
How do I link or add the field with all my users called "username" from my main table to another table so I can run checks and compare values without having to add a ton of rows to my main table? This would be a much cleaner and more organized setup.
Table called login_users. This is my main table that stores their basic information
username email password
Anthony user#email.com
Josh user#email.com
Tsuyoshi user#email.com
Table 2 called badge_status. This table will hold their status with whether or not they have unlocked an achievement on my site. I want to bring in the usernames.
username badge1 badge2
Anthony locked unlocked
Josh unlocked locked
Tsuyoshi unlocked locked
Also, could table 2 automatically be updated with a new user when they sign up since all new sign ups are imported into the first table. As a side note, I am using phpmyadmin.
Thanks for any help with getting this set up. Very much appreciated.
I think you should normalize your data by using the following schema instead:
login_users [Table]
username
email
password
badges [Table]
BadgeId int PRIMARY KEY
BadgeName
... (any other relevant columns)
users_badges [Table]
username (foreign key constraint to username column on the login_users table)
BadgeId (foreign key constraint to BadgeId column on the badges table)
This will allow you add as many badges as you want without having to ever change your database schema or scripts.
I don't really understand why you are separating out these tables. In theory, there is a one-to-one relationship between the two. Your query "could table 2 automatically be updated with a new user when they sign up since all new sign ups are imported into the first table" further supports the argument why splitting these tables simply creates unnecessary overhead.
Other sources of overhead include overly complicated JOINs to get the data out and the need to add an additional unique constraint on badge_status.username as well as a foreign key.
If you truly wish to separate out these tables, I would suggest the following setup instead which makes querying for specific badges and adding new badges very easy:
login_users: username, email, password, ...
badges: id, name, description, ...
users_badges: username, badge_id, status, unlocked_date, ...