phpMyAdmin
 sql >> Base de données >  >> Database Tools >> phpMyAdmin

Comment configurer la relation entre les tables dans phpMyAdmin

La contrainte de clé étrangère table2 signifie que toute valeur de l'ID client de la table 2 doit apparaître en tant qu'ID client dans la table 1. Vous obtenez l'erreur car vous insérez un ID client dans la table2 qui n'apparaît pas dans la table1.

Étant donné que le SGBD génère les ID client de la table 1 par incrémentation automatique, si vous insérez une ligne, vous devez obtenir cette valeur afin d'insérer une ligne utilisant cet ID client dans la table 2.

Je suppose que vous dites "J'ai déjà établi une relation entre table1 et table2" pour signifier "J'ai déclaré une contrainte de clé étrangère". Et je suppose que vous pensez que cela signifie "après avoir inséré dans table1, le SGBD utilisera la valeur de clé générée automatiquement comme valeur de clé étrangère lors de l'insertion dans table2". Mais ça ne veut pas dire ça. Vous devez le faire vous-même. La contrainte de clé étrangère signifie simplement que le SGBD vérifie que chaque valeur customerId table2 apparaît comme une valeur customerId table1.

Vous pouvez et devez utiliser n'importe quelle valeur de clé précédemment insérée comme valeur correspondante lorsque vous insérez dans une table une clé étrangère à cette clé.

Pour récupérer la valeur de clé auto-incrémentée générée par le SGBD, utilisez LAST_INSERT_ID() :

INSERT INTO table1 (CustomerName,Address,State)
VALUES('value1','value2','value3');
INSERT INTO table2 (customerId,product,cost)
VALUES(LAST_INSERT_ID(),'valueA','valueB');

C'est pour ça. Mais voici les problèmes si vous ne l'utilisez pas.

Tout d'abord, si vous n'êtes pas dans une transaction sérialisée, vous devez utiliser LAST_INSERT_ID(). Parce qu'après votre insertion table1 mais avant votre insertion table2, d'autres pourraient avoir ajouté des lignes et/ou supprimé des lignes, y compris votre nouvelle ligne et/ou modifié des lignes, y compris votre nouvelle ligne. Vous ne pouvez donc pas compter sur l'interrogation de table1 après son insertion pour obtenir une valeur d'ID client que vous savez que vous avez ajoutée.

Deuxièmement, supposons que vous êtes dans une transaction sérialisée et que vous n'utilisez pas LAST_INSERT_ID().

Si (CustomerName,Address,State) est aussi une super-clé de table1, c'est-à-dire que ses valeurs sont uniques, c'est-à-dire que SQL UNIQUE/KEY/PK est déclaré sur tout ou partie de ses colonnes, alors vous pouvez l'utiliser pour interroger le nouveau customerId associé :

set @customerId = (
    SELECT customerId
    FROM table1
    WHERE CustomerName = 'value1'
    AND Address = 'value2'
    AND State = 'value3');
INSERT INTO table2 (customerId,product,cost)
VALUES(@customerId,'valueA','valueB');

Mais si (CustomerName,Address,State) n'est pas une super-clé de table1, vous ne pouvez pas le faire. Parce que d'autres lignes qui sont des doublons pour cette sous-ligne pourraient être dans table1. Ainsi, vous pouvez récupérer plusieurs lignes. Vous ne sauriez donc pas lequel est le plus récent. Au lieu de cela, vous devez interroger table1 avant l'insertion, puis insérer, puis trouver la différence entre les anciens et les nouveaux ensembles d'ID client :

CREATE TEMPORARY TABLE table1old (
    customerId (int) PRIMARY KEY
    );
INSERT INTO table1old
SELECT customerId FROM table1;

INSERT INTO table1 (CustomerName,Address,State)
VALUES('value1','value2','value3');

set @customerId = (
    SELECT customerId
    FROM table1
    WHERE CustomerName NOT IN table1old);
INSERT INTO table2 (customerId,product,cost)
VALUES(@customerId,'valueA','valueB');

Utilisez simplement LAST_INSERT_ID().

PS :Il est intéressant de noter que, compte tenu des définitions du tableau, on pourrait idéalement écrire :

INSERT INTO (
    SELECT CustomerName,Address,State,A,B
    FROM table1 JOIN table2
    USING (CustomerId))
VALUES('value1','value2','value3','valueA','valueB')

car il n'y a qu'une seule paire de nouvelles valeurs table1 et table2 qui peuvent en résulter. Il existe quelques mises à jour légales via des vues dans SQL, bien qu'aucune n'implique actuellement plusieurs tables dans MySQL