I am working on a PHP application which Db design was created by another guy who added FK constraints(On Cascade delete etc) between tables. So far what I am used to do is to put a FK in another table. For instance we have two tables:
Users
ID
Name
CountryID
Countries
ID
Name
At application Level I will create two Separate INSERTs calls. If FK is present, then what change do I need to make at my application level?
You need to make sure that the row you reference with the FK exists before you create the row in the other table.
… but you are probably doing this already as that is the logical order to create the rows.
Foreign keys enforce referential integrity.
These constraints guarantee that a row in a table order_details with a field order_id referencing an orders table will never have an order_id value that doesn't exist in the orders table.
Foreign keys aren't required to have a working relational database (in fact MySQL's default storage engine doesn't support FKs), but they are definitely essential to avoid broken relationships and orphan rows (ie. referential integrity). The ability to enforce referential integrity at the database level is required for the C in ACID to stand.
Related
I have multiple tables in a Laravel app with 1-to-1 relationship such as users , users_settings , user_financial
And some 1-to-many relationships such as users_histories
My questions are:
1. Should I always include incremental id at the first?
for example is the id necessary in the Table #2 below?
Table 1:
id (primary,increments) , name, email, password
Table 2:
id (primary,increments), user_id, something_extra
^ why does every guide include this? // e.g. https://appdividend.com/2017/10/12/laravel-one-to-one-eloquent-relationships/
Can't I just use user_id as primary key and skip the incremental key? because I want to auto insert it on table 2 as soon as data is inserted in table 1.
2. How should I name 1-to-1 and 1-to-many tables in Laravel? `
I searched but didn't find any naming convention for different type of relationships...
Currently I do:
users table with primary key id is the base.
1-to-1: users_settings with foreign key user_id
1-to-many: users_histories foreign_key user_id
many-to-many: users_groups foreign_key user_id
should the first two tables be named settings/setting , histories/history instead? sorry I'm a little confused here.
I actually asked a similar question around 2 days ago. Its up to you but I'd say yes. In my case if I don't auto_increment all my ids in the related tables, data won't be associated with the correct user. However, there is an argument for saying auto_increment columns should not be used in this case, but they are useful for other things. According to some, the relationships might not be as meaningful so it'd be up to you and down to the specifics of you data tables for how meaningful the relationship will be. Regardless, you should research more into the advantages of auto_incrementing all your ids in related tables, as well as possible disadvantages before deciding what you want to do. Either way is fine, but they offer different advantages and disadvantages- which you'll need to compare and what works best for your specific case.
This is a well debated topic about the primary key. IMHO, No, you shouldn't. Every column in database should have a purpose. Following this, for your example, I agree that the auto_increment id is redundant and this is simply because it doesn't have a purpose. The second table is still uniquely describing the user so that the primary key should be the user_id.
Beside the above, there is another principle for me to decide whether I need the auto_increment id: whether I can see a table as an entity. For example, user is clearly an entity, but a relationship is not (in most cases), i.e., composite key can serves the purpose. But when an relationship table is extended to have more attributes and it starts to make sense for it to have an auto_increment id.
I don't have much experience on Laravel, but the naming for a database table should not be dictated by a framework. Comparing history and user_history, what a new DBA or developer expect from the two names without looking its data? user_history describes the table more precisely
At past, I was used to make a table relationship programmatically, which is quite handy since you don't need to make FK constraint to each table which have relation.
But, I wonder what is the differences or the advantages of giving a FK constraint to tables that have relation, instead of just creating an attribute and retrieve them programmatically (calls the tables where field = another table PK).
Just some information, I work on php independent MVC framework without any dependency to eloquent or something else.
Hope someone give me some short lesson on this :D Thank you and have a nice day!
There are certain principles that you should follow while coding and development, I can say that there is no issue whether or not you create a foreign key constraint to a table that has relation or not but you know that won't restrict the column to have only those values that are being referenced by it. So basically it is not a good DB Schema and may lead to inconsistencies. For example deleting a parent table's row you will have to manually delete the child table's row on the other hand if you have a foreign key constraint that to onDelete = cascade, your database will automatically take care of everything and there won't any inconsistencies.
I am working with mysql and codeigniter using the redbean ORM. After implementing a foreign key for many to many assosciation I got the following error when I run:
drop TABLE IF EXISTS `temp`
Integrity constraint violation: 1217 Cannot delete or update a parent row: a foreign key constraint fails thrown
I then entered SHOW ENGINE INNODB STATUS into phpmyadmin. The output includes:
LATEST FOREIGN KEY ERROR------------------------: Cannot drop table `db1`.`temp`because it is referenced by `db1`.`temp_workers`.
In other words another table references the FK. For testing purposes I think the best thing to do is to drop all the associated tables and recreate them using the controller I'm testing. Is this the best way to go? I've tried:
drop TABLE IF EXISTS `temp` `temp_workers`
, but I'm still getting the above error, and the drop command does not work. Also:
truncate TABLE `temp`, `temp_workers`
gives:
You have an error in your SQL syntax
As mentioned in the comments you have to drop any tables with FK contraints to other tables, first, then you can drop the tables being linked to.
Example:
User
id: 1
name: Mike
Address
id: 1
user_id: 1 (FK constraint to User.id table.column)
address_1: 555 Main Street
This setup is a 1:1 relationship (more on data normalization), where one user row can reference one address row, and because the address row is dependent upon the existence of the user row, if you attempt to remove the user row, you will see the errors you mentioned.
But if you drop the Address table first, everything works as expected because the User table is not FK to any other table.
Ensuring referential integrity within your schema ensures you do not end up with orphaned rows, which will permeate throughout your data driven application.
You could also issue the following commands:
SET foreign_key_checks = 0;
# Do Stuff
SET foreign_key_checks = 1;
But I would strongly advise against this, as you could break the referential integrity of your data, and end up in a real mess. I've seen someone do this in an enterprise environment and it took them weeks to clean it up. However, if you are doing this STRICTLY for testing purposes; like writing unit tests, or just learning, and you didn't want to drop the tables every time, you could do this:
# Because we remove the foreign key check, we can truncate in any order
SET foreign_key_checks = 0;
TRUNCATE TABLE user;
TRUNCATE TABLE address;
SET foreign_key_checks = 1;
Proper schema design using foreign key constraints goes along way to building a good foundation for any data driven application. It will take time to get your head around when to use, and how to construct foreign key constraints, but over time you will begin to understand. A good way to get started is to download an open source project like magento, wordpress, or vbulletin and take a look at their schemas. You can even introspect these schemas using MySQL workbench and view their Entity-Relationship Diagrams (ERDs), which will visually demonstrate links between tables.
Let's say you have got two tables like the following in a MySQL database:
TABLE people:
primary key: PERSON_ID,
NAME,
SURNAME, etc.
TABLE addresses:
primary key: ADDRESS_ID,
foreign key: PERSON_ID,
addressLine1, etc.
If you manage the creation of rows (in both table) and the retrieving of data trough PHP do you still need to create a physical relationship in the database? If yes, why?
Yes, one concrete reason is to have faster retrieving of rows if you want to join tables. Creating a foreign key constraint automatically creates a an index on the column.
So table address' schema should look like this, (assuming People's table primary key is PERSON_ID)
CREATE TABLE Address
(
Address_ID INT,
Person_ID INT,
......,
CONSTRAINT tb_pk PRIMARY KEY (Address_ID),
CONTRRAINT tb_fk FOREIGN KEY (Person_ID)
REFERENCES People(Person_ID)
)
Strictly speaking: You don't need to use FK's. careful indexing and well written query's might seem to be sufficient. However FK's and certainly FK constraints are very useful when it comes to securing data consistency (avoiding orphaned data, for example)
Suppose you wrote your application, everything is tested and it works like a charm. Great, but who's to say that you'll be around every time something has to be changed? Are you going to maintain the code by yourself or is it likely that someone else might end up doing a quick fix/tweak or implement another feature down the road? In reality, you're never going to be the only one writing and maintaining the code, and even if you are the only one maintaining the code, you're almost certainly going to encounter bugs as time passes...Foreign keys inform both your co-workers and you that data from tbl1 depends on the data from tbl2 and vice-versa. Just like comments, this makes the application easier to maintain.
Bugs are easier to detect: creating a method deleting a record from tbl1, but forgetting to update tbl2 to reflect the changes made to the first tbl. When this happens, the data is corrupted, but the query that caused this won't result in errors: the SQL is syntactically correct and the action it performs is the desired action. These kind of bugs could remain hidden for quite some time, and by the time this is spotted, god knows how much data has been corrupted...
Lastly, and this is an argument that is used all too often, what if the connection to the DB is lost mid-way through a series of update/delete query's? FK Constraints enable you to cascade certain actions. I haven't actually seen this happen, but I know of anybody who doesn't write code to protect against just such a scenarioDeleting or updating several relational records, but mid-way, the connection with the DB gets cut off for some reason. You might have edited tbl2, but the connection was lost before the query to tbl1 was sent. Again, we end up with corrupted data. FK CASCADE's are very useful here. Delete from tbl1, and set an ON DELETE CASCADE rule, so that you can rest assured that the related records are deleted from tbl2. In the same situation, ON DELETE RESTRICT, can be a fairly useful rule, too.
Note that FK's aren't the ultimate answer to life, the universe and everything (that's 42 - as we all know), but they are a vital part of true relational database-designs.
Referential integrity is an article that you should read and comprehend.
there are two ways
-first one is to handle all the things on coding end manage the things on deleting or updating a record
but when you use foreign key you are enforcing the relation and Db don't allow you to delete records with foreign key constraint especially when you don't want to delete the records related to it there is some situations accrue where you need to do this kind of tasks.
-Second way is to manage things on the Db side. If you have 1-to-many or many-to-many relations in database, foreign keys will be very useful. Also they have some good actions - RESTRICT, CASCADE, SET NULL, NO ACTION those can do some work for you
In mysql, I've got the following:
TABLE docs (
ID
title
content
)
TABLE specialDocs (
docID -> docs(ID)
userID -> users(ID)
)
So specialDocs is a subset of documents that can belong to users.
I am wondering: Is it possible to specify a cascade rule so that when a user is deleted, the docs that belong to that user are automatically deleted? (I realize it would be simple to do this if the pointer to users(ID) was a column within the table "docs". However I am unclear if it is possible with a join table like the above...)
Thanks in advance for your help
I wouldn't do that - your specialdocs table is a many-to-many table, so multiple users could be related to the same document. What you want, shouldn't be allowed without deleting the other references first - which a cascade delete won't do. And if you don't have referential integrity (IE: MyISAM table), then you'll have orphaned records in specialdocs to a document that no longer exists.
Cascade on delete is a referential integrity feature, so it won't be available for MyISAM tables - you'd have to use a trigger for that. Given the need to check for referential dependencies, I'd use a trigger for Innodb tables as well to get rid of the related specialdocs records first...