Mysql
 sql >> Base de données >  >> RDS >> Mysql

Comment utiliser des clés étrangères avec PHP

Désambiguïsation des colonnes/contraintes de clé étrangère

En supposant que vous faites référence aux contraintes de clé étrangère , la réponse courte serait vous ne les utilisez tout simplement pas .

Et voici la longue :

Nous avons l'habitude de désigner les colonnes comme des clés étrangères aux autres tableaux. Surtout pendant le processus de normalisation, des phrases comme "user_purchase.i_id est une clé étrangère vers les items tableau" serait très courant. Bien que ce soit une manière parfaitement valide de décrire la relation, elle peut devenir un peu floue lorsque nous atteignons la phase de mise en œuvre.

Supposons que vous ayez créé vos tables sans la FOREIGN KEY clauses :

CREATE TABLE user(
  id INT(11) NOT NULL AUTO_INCREMENT,
  username VARCHAR(50) NOT NULL,
  password VARCHAR(20) NOT NULL,
  PRIMARY KEY (id)
);

CREATE TABLE items(
  i_id INT(11) NOT NULL AUTO_INCREMENT,
  name TINYTEXT NOT NULL,
  price DECIMAL(8,2) NOT NULL,
  PRIMARY KEY (i_id)
);

CREATE TABLE user_purchase(
  i_id INT(11) NOT NULL,
  name TINYTEXT NOT NULL,
  id INT(11) NOT NULL,
);

Notez que, du point de vue relationnel, la clé étrangère colonnes sont toujours implémentés . Il y a une colonne qui référence le user tableau (id ) et un autre qui référence les items tableau (i_id ) -- mettons le name colonne de côté un instant. Considérez les données suivantes :

  user              user_purchase    items
| id  username |    | id  i_id |    | i_id  name            price |
| 23  john     |    | 55   10  |    |  10   chocolate bar    3.42 |
| 55  mary     |    | 70   10  |    |  33   mobile phone    82.11 |
| 70  fred     |    | 70   33  |    |  54   toothpaste       8.67 |
                    | 55   10  |    |  26   toy car          6.00 |
                    | 70   26  |

Le rapport est là. Il est implémenté au moyen du user_purchase table, qui contient des informations sur qui a acheté quoi . Si nous devions interroger la base de données pour un rapport pertinent, nous ferions :

select * from user_purchase p
join user u on (p.id=u.id)
join items i on (p.i_id=i.i_id)

Et c'est ainsi que nous utilisons la relation et la clé étrangère colonnes impliqué.

Maintenant, et si nous faisions :

insert into user_purchase (id,i_id) values (23,99)

Apparemment, il s'agit d'une entrée invalide. Bien qu'il y ait un utilisateur avec id=23 , il n'y a pas d'élément avec i_id=99 . Le RDBMS permettrait que cela se produise, car il ne sait pas mieux . Encore.

C'est là que les contraintes de clé étrangère entrer en jeu. En spécifiant FOREIGN KEY (i_id) REFERENCES items(i_id) dans le user_purchase définition de table, nous donnons essentiellement au SGBDR une règle à suivre :entrées avec i_id les valeurs qui ne sont pas contenues dans le items.i_id colonne ne sont pas acceptables . En d'autres termes, alors qu'une colonne de clé étrangère implémente la référence , une contrainte de clé étrangère applique l'intégrité référentielle .

Notez, cependant, que le select ci-dessus ne changerait pas, simplement parce que vous avez défini une contrainte FK. Ainsi, vous n'utilisez pas les contraintes FK, le SGBDR le fait, afin de protéger vos données.

Licenciements

Demandez-vous :pourquoi voudriez-vous cela ? Si les deux clés étrangères doivent servir le même objectif, la redondance finira par vous causer des ennuis. Considérez les données suivantes :

 user_purchase                   items
| id  i_id  name           |    | i_id  name            price |
| 55   10   chocolate bar  |    |  10   chocolate bar    3.42 |
| 70   10   chocolate bar  |    |  33   mobile phone    82.11 |
| 70   33   mobile phone   |    |  54   toothpaste       8.67 |
| 55   10   toothpaste     |    |  26   toy car          6.00 |
| 70   26   toy car        |

Quel est le problème avec cette image? L'utilisateur 55 acheter deux tablettes de chocolat, ou une tablette de chocolat et un dentifrice ? Ce type d'ambiguïté peut entraîner de nombreux efforts pour maintenir la synchronisation des données, ce qui serait inutile si nous ne gardions qu'une des clés étrangères. En fait, pourquoi ne pas laisser tomber le name colonne entièrement, puisqu'elle est impliquée par la relation.

Bien sûr, nous pourrions résoudre ce problème en implémentant une clé étrangère composite, en définissant PRIMARY KEY(i_id,name) pour les items table (ou en définissant un UNIQUE(i_id,name) supplémentaire index, cela n'a pas vraiment d'importance) puis en définissant un FOREIGN KEY(i_id,name) REFERENCES items(i_id,name) . De cette façon, seuls les couples (i_id,name) qui existent dans les items table serait valide pour user_purchases . Outre le fait que vous en auriez encore un clé étrangère , cette approche est totalement inutile, à condition que le i_id la colonne est déjà suffisante pour identifier un élément (on ne peut pas en dire autant pour le name colonne...).

Cependant, il n'y a pas de règle interdisant l'utilisation de plusieurs clés étrangères pour une table. En fait, il y a des circonstances qui exigent une telle approche. Prenons une person(id,name) table et un parent(person,father,mother) un, avec les données suivantes :

 person             parent
| id  name    |    | person  father  mother |
| 14  John    |    |   21      14      59   |
| 43  Jane    |    |   14      76      43   |
| 21  Mike    |
| 76  Frank   |
| 59  Mary    |

Évidemment, les trois colonnes du parent table sont des clés étrangères pour person . Pas pour la même relation , cependant, mais pour trois différents :Comme les parents d'une personne sont aussi des personnes, les deux colonnes correspondantes doivent référencer la même table person Est-ce que. Notez cependant que non seulement les trois champs peuvent mais aussi doivent parrainer une person différente s dans le même parent ligne, puisque personne n'est son propre parent et que le père de personne n'est pas non plus sa mère.