I've been toying with MySQL today and reading their documentation, gotten some handy information of optimization and a lot of things I didn't know. Now I've been adding foreign keys to my web application because it add constrains and I see it quite helpful.
My doubt is, right now there is a Roles table and a Users table, I set a relation on user's RoleID that when the role ID is removed (from the Roles table, parent) it should the user is deleted.
Now I kinda have the answer but I prefer someone to confirm, the ID has to match? or does the foreign key takes action regardless if it matches or not?
The foreign key constraints will only take place where the ID is matched. In other words, it won't remove users of different RoleIDs, only those users which have the RoleID of the deleted Role.
Related
I have a table called users. This table has a foreign key called project_id in another table called projects. Users on my page will see a dropdown that contains all projects and will be able to select one of them. I will then use the primary key of the selected project to be a foreign key to the newly created user.
Now in laravel's eloquent model, I have read that foreign keys should always be guarded (can't be mass assignable) for security. I don't really understand why that is. Suppose I validated that the project_id exists in the projects table, shouldn't I be confident that the value is valid and can now be mass assigned to the User model? Is there any other reason I'm missing why people say foreign keys should always be guarded?
Foreign keys should be guarded as a best practice, but if you are absolutely sure you are sanitizing your input there is no reason why you shouldn't unguard project_id.
There are other cases where guarding should really be kept - for example, your users table has a is_paid_member field that indicates the user has paid real money to unlock certain features on your site. Let's assume you did not guard that field, and the user goes to his profile page, manipulates the form by adding a <input type="hidden" name="is_paid_member" value="1"> field, and submits the form.
If you are doing a mass update when saving the profile details - something like $user->update($request->input()) then the user just got himself a paid account for free.
I'm implementing a flashcard app, hence my FLASHCARDS table contains fields such as QUESTION and RESPONSE, and my USERS table is just that - names and personal info of my flashcard app.
Here's where I get confused. The FLASHCARDS table will hold 100s of questions and responses categorized into "groups" of flashcards (or decks). When the USERS "use" the flashcards they will also be able to decide if the question was EASY, NORMAL, or DIFFICULT - hence modifying the time till the card is next shown.
If I only had one user this wouldn't be a problem - I'd just modify the FLASHCARDS table accordingly, but I´ll also have 100s of users. How can I modify FLASHCARDS table depending on each USERS decision of EASY, NORMAL or DIFFICULT and keep record of all of this for each user (I imagine in USERS table).
You've got a many-to-many relationship between the "Flashcard" entity and the "User" entity.
A particular "User" makes a decision about a particular "Flashcard".
A "User" can make a decision on zero, one or more "Flashcard".
A "Flashcard" can be decided by zero, one or more "User".
That's a classic many-to-many relationship.
In the relational model, we introduce a new relationship table, that establishes the relationship between "User" and "Flashcard"
As an example of what this table might look like:
CREATE TABLE user_flashcard
( user_id INT UNSIGNED NOT NULL COMMENT 'fk ref user'
, flashcard_id INT UNSIGNED NOT NULL COMMENT 'fk ref flashcard'
, decision VARCHAR(30) COMMENT 'EASY,NORMAL,DIFFICULT'
, PRIMARY KEY (user_id,flashcard)
, CONSTRAINT FK_user_flashcard_user
FOREIGN KEY (user_id) REFERENCES user(id)
, CONSTRAINT FK_user_flashcard_flashcard
FOREIGN KEY (flashcard_id) REFERENCES flashcard(id)
)
You could add additional attributes, for example: the last time the user viewed the flashcard, the number of times the user has viewed it.
You also need to consider whether this is just a pure relationship, or if this is might actually be an entity in your model.If we have repeating attributes, or any other entities might be related to this table, we'd likely want to introduce a simple primary key (id) that other tables can reference in a foreign key.
We also want to think about this, do we want a user to have more than one decision on a flashcard? Does (user_id,flashcard_id) need to be unique, or should it be non-unique.
The key to database design is data analysis. And one of the best tried-and-true techniques for "doing" data analysis is Entity Relationship Modeling.
FOLLOWUP EXAMPLE DEMONSTRATION
As a demonstration of how this "relationship" table works, I've created a very short SQL Fiddle, demonstrating the kind of questions that can be fairly easily answered using some fairly simple SQL.
SQL Fiddle Here http://sqlfiddle.com/#!9/090ee/5
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 wish to know what SQL is needed to be passed to implement multiple categories for an article.
I have created 3 tables.
ARTICLES:
id, title, content
CATEGORIES:
id, name
RELATION:
article_id, cat_id
I am successfully able to create the first two tables, and store data in them when user submits the form. But, I have no clue how to update the RELATION table. I searched on stackoverflow, and I learned that I need to use a many to many relationship. I have idea about it. But, I do not know how to do it practically i.e. the SQL.
The Categories are obviously added while the post is published, So i need to update this table only after the first two tables have been updated.
If someone can guide me to a tutorial or in the right direction I shall be greatful.
Assuming that post and article are synonyms, then each time a new post is published and its category is determined you need to 'INSERT' a record into 'RELATION' table.
When you originally create tables you will need to identify Primary and Foreign keys (CONSTRAINTS) and (if so desired) specify whether CASCADE should be enabled.
Apparently you already know how to CREATE tables and INSERT rows.
You may want to Google for PRIMARY KEY, FOREIGN KEY, CASCADE ON DELETE in conjunction with MYSQL and PHP.
Also see if the following helps any: How do I use on delete cascade in mysql?.
This should be taken care of by your SQL DBMS. For example, if you set your relationship's foreign keys to cascade delete or update, when something changes in the parent, the children will also be deleted/updated. Can you give me an example of an update that you would expect to make to the first two tables and the resulting update to the RELATION table?
I am trying to understand relationships fully, and have gone through alot of tutorials. Still i linger on a few things (using MySQLWORKBENCH):
1. Every user can upload a product
2. Every product can have multiple categories, bids, ratings, etc
3. Every user can have multiple phonenumbers
(there are more, but this is the basic setup)
Is this correct?:
1 - I used a 1:n relationship, since every user can upload multiple products.
2 and 3. I used n:m relationship, since there can be multiple products with multiple categories, bids, ratings, etc.
DELETE/UPDATE:
I used ON UPDATE CASCADE and ON DELETE CASCADE everywhere where there is a foreign key...that being 'product', 'category_tags_has_products', 'bid_price_has_product', 'phone_has_user'.
I tried to delete a product like this (php): mysql_query("DELETE FROM product WHERE id='$id'");
I get a 1054 error, which is a foreign key error.
What are the best practises here? It is to my understanding that i shouldn't need to do deletions in any other than the parent-table?
Thanx!
You have a lot of identifying relationships, which mean that the foreign key form part of the primary key on the second table. This is not necessary in most instances, and is only really useful in instances such as link tables.
To this end I would change the user->product link to be non-identifying, which will make user_id a Foreign Key instead of being part of the Primary Key. In workbench the shortcut for a 1:n non-identifying relationship is key '2' (where as '4' is identifying). This in turn should remove the user_id fields from the tables which product links onto.
When you delete a product, it should cascade to the 3 link tables that it links to. At present it may be that it is trying to delete from users also depending on how the FK is set up. The following should cascade deletions (assuming a deletion is permanent and you just want to clear out all linked records)
DELETE FROM product -> deletes from any table with product_id in
DELETE FROM user -> deletes from any table with user_id in
The same applies for phone, rating, bid_price, category_tags.
I hope this if of use, if you need any further pointers feel free to shout :)
The relations look correct.
To find out what is wrong with your query check the $id variable.
Or check the whole query and then run it in the console/phpMyAdmin/etc:
$query = "DELETE FROM product WHERE id='$id'";
var_dump($query);
mysql_query($query);
P.S.: and don't forget to escape all data got from the users! Like this:
$id = mysql_real_escape_string($_GET['id']);