Besides help describe the relationship in the models, foreign keys are mainly used to maintain data integrity, ie imagine that you have two tables linked by a foreign key and have data in the table B
linked to a specific row in the table A
, then you, if you try to delete this line specifies the bank will prevent you and will send an error.
Before the foreign key we had to control and do this kind of prevention at the application layer or with "triggers", it was a very difficult job and was not always efficient.
I will quote some types of relationships:
one-to-Many, 1 for many (1:n
):
If on the table A
I have a row with id 3 and in the table B
I have two lines attached to id 3 and I try to delete this row from table A
an error will occur.
1 to N, one-to-many or 1:N (one-to-Many) to refer to one of the types of relationships that can be established between the fields of two tables: each tuple of a table can relate to N tuples of the other table. However, each tuple of the second table only relates to a single tuple of the first.
https://en.wikipedia.org/wiki/One-to-many_(data_model)
Many-to-Many, many to many (n:m
)
If on the table A
we have two ids 35 (john) and 36 (mary) and in the table B
we have the following values:
id | nome
--------------
1 | carro
2 | casa
3 | terreno
4 | kitnet
Then we have a third table that will make the interaction between A and B, we can call it A_tem_B
that in an example would be:
id_A | id_B
--------------
1 | 35
1 | 36
2 | 35
3 | 36
4 | 36
What basically the table A_tem_B
is saying is:
- John (id 35) has car
- Maria (id 36) has car
- João has a home
- Maria has land
- Maria has kitnet
If I try to delete kitnet
(id 4), an error will occur because it is linked to Maria.
If I try to delete carro
(id 1), an error will occur because Mary and John are linked to the car.
In the relational database model, any of the expressions N for N, many-to-many (Many-to-Many), or N:N (sometimes also expressed as N:M) is used to refer to one of the types of relationships that can be established between the fields of two tables: for each value of a table field, there may be N values in the other table field and vice versa.
In relational databases, this relationship is consummated through a link table that matches both sides with relationship 1 to N for each side. The primary key arises naturally, and is composed by the junction of the primary keys of the interconnected tables.
https://en.wikipedia.org/wiki/Many-to-many_(data_model)
Even without foreign key we can have a relationship between different tables, but the hard thing is to maintain integrity even if using triggers for such service as I mentioned earlier.
Problem of the matter
If you are able to insert hobbies into the table is because there is something wrong in how you modeled, it is not a problem with FK but rather the way you did, see an example that works:
The example is in mysql and innoDB and is an example of many for many, ie two users can have the same hobby (do not know which database is using), sql:
CREATE TABLE IF NOT EXISTS `usuarios` (
`idusuarios` INT NOT NULL AUTO_INCREMENT,
`nome` VARCHAR(45) NULL,
PRIMARY KEY (`idusuarios`) )
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS `hobbies` (
`idhobbies` INT NOT NULL AUTO_INCREMENT,
`hobbie` VARCHAR(45) NULL,
PRIMARY KEY (`idhobbies`) )
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS `usuarios_has_hobbies` (
`usuarios_idusuarios` INT NOT NULL,
`hobbies_idhobbies` INT NOT NULL,
PRIMARY KEY (`usuarios_idusuarios`, `hobbies_idhobbies`) ,
INDEX `fk_usuarios_has_hobbies_hobbies1_idx` (`hobbies_idhobbies` ASC) ,
INDEX `fk_usuarios_has_hobbies_usuarios_idx` (`usuarios_idusuarios` ASC) ,
CONSTRAINT `fk_usuarios_has_hobbies_usuarios`
FOREIGN KEY (`usuarios_idusuarios`)
REFERENCES `usuarios` (`idusuarios`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_usuarios_has_hobbies_hobbies1`
FOREIGN KEY (`hobbies_idhobbies`)
REFERENCES `hobbies` (`idhobbies`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
Then enter a user and a hobby, then take the id
hooby and try to add with a user id that does not exist, will give this error:
1452 - Cannot add or update a Child Row: a Foreign key Constraint fails (foo
.usuarios_has_hobbies
, CONSTRAINT fk_usuarios_has_hobbies_hobbies1
FOREIGN KEY (hobbies_idhobbies
) REFERENCES hobbies
(idhobbies
) ON DELETE NO ACTION ON UPDATE NO ACTION)
However by its explanation whether the example of hobbies is hypothetical, so maybe your need isn’t n:m
, may be 1:n
, so the example would be like this:
CREATE TABLE IF NOT EXISTS `usuarios` (
`idusuarios` INT NOT NULL AUTO_INCREMENT,
`nome` VARCHAR(45) NULL,
PRIMARY KEY (`idusuarios`) )
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS `hobbies` (
`idhobbies` INT NOT NULL AUTO_INCREMENT,
`hobbie` VARCHAR(45) NULL,
`usuarios_idusuarios` INT NOT NULL,
PRIMARY KEY (`idhobbies`) ,
INDEX `fk_hobbies_usuarios_idx` (`usuarios_idusuarios` ASC) ,
CONSTRAINT `fk_hobbies_usuarios`
FOREIGN KEY (`usuarios_idusuarios`)
REFERENCES `usuarios` (`idusuarios`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
In this case I created a user:
INSERT INTO `usuarios` (`idusuarios`, `nome`) VALUES ('João'); #id 1
So try to create a hobby for him, like this:
INSERT INTO `hobbies` (`hobbie` , `usuarios_idusuarios` ) VALUES ('basquete', 1); #id: 1
Then try creating a hooby for a user that doesn’t exist:
INSERT INTO `hobbies` (`hobbie` , `usuarios_idusuarios` ) VALUES ('natação', 1900);
This error must occur because id 1900 does not exist in the table usuarios
:
1452 - Cannot add or update a Child Row: a Foreign key Constraint fails (foo2
.hobbies
, CONSTRAINT fk_hobbies_usuarios
FOREIGN KEY (usuarios_idusuarios
) REFERENCES usuarios
(idusuarios
) ON DELETE NO ACTION ON UPDATE NO ACTION)
I did the tests here (locally) and it worked, occurring the errors cited when due.
Software for modeling in Mysql
A good software to get around these problems when modeling is the Mysql Workbench (mysql) that supports Windows, Linux and OS X:
The Workbench is quite simple to use, but it is not easy to explain with words (maybe in the future I edit this answer), anyway follows 3 videos lessons that can be useful:
It was worth a lot brother! I had read about these forms
1:1
1:N
andN:N, mas so com sua resposta entendi realmente como cada um funciona. Acho que tem um pequeno erro na resposta, no seu segundo
Inserto
idnão seria 1 né, seria um
id` nonexistent in table A, like 100? I have this software on my PC, never touched it rs always used Heidisql and Phpmyadmin, thanks for the tip!– Leonardo
@Leonardovilarinho Heidisql and Phpmyadmin are to manage the bank, to model is the Workbench, are different tasks ;) - Here you refer:
INSERT INTO hobbies (hobbie , usuarios_idusuarios) VALUES ('basquete', 1); #id: 1
? It would be 1 yes, because the table is autoincrement and in hobbies there were no data yet. Please test both examples ;) - Ps.: I added 3 videos of the Workbench, I didn’t watch, but they seem useful to you.– Guilherme Nascimento
Yes, they are more for management, I have never used any for modeling. I refer to line
INSERT INTO hobbies (hobbie , usuarios_idusuarios ) VALUES ('natação', 1);
(thirdinsert
, because on the phone it is bad to read rs), in it the value ofusuarios_idusuarios
should be 2 or higher, to give the error. And in the firstinsert
would not need to have specified the columnidusuarios
since she isauto increment
. Thank you, the examples made me understand!– Leonardo
@Leonardovilarinho kkkkkk well noticed, it was 1900 the value, do not know why I disappeared with part of the stretch rs
– Guilherme Nascimento
I was going to ask a question that I think you can help me William. I can maintain a system without foreign keys in the tables?
– DiChrist
@Dichrist yes is possible, but the problem is that the logic of linking between different tables will have to be all in the application (for example PHP classes) and it will be very difficult to create something without bugs, besides that you will not have a diagram (Workbench has one) to know what links with what, will be fully oriented to application... There are frameworks that do this as Laravel it is possible to relate by application, only it has two problems (difficulties), depending on the type of bank will not be able to do rollback, unless the chosen framework simulates and will have to learn the framework :/
– Guilherme Nascimento
excellent William, that’s what I needed to know. VLW!
– DiChrist