2010-03-28 7 views
2

Faire mes premiers essais avec des clés étrangères dans une base de données mySQL et tentent de faire un insert, qui échoue pour cette raison: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint failsTravailler avec les clés étrangères - ne peut pas insérer

Est-ce que cela signifie que les clés étrangères limitent INSERTS ainsi comme DELETS et/ou MISES A JOUR sur chaque table qui est appliquée avec des relations de clés étrangères?

Merci!

Description Mise à jour:

Products 
---------------------------- 
id | type 
---------------------------- 
0  | 0 
1  | 3 

ProductsToCategories 
---------------------------- 
productid | categoryid 
---------------------------- 
0   | 0 
1   | 1 

table de produit a la structure suivante

CREATE TABLE IF NOT EXISTS `alpha`.`products` (
    `id` MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT , 
    `type` TINYINT(2) UNSIGNED NOT NULL DEFAULT 0 ,  
    PRIMARY KEY (`id`) , 
    CONSTRAINT `funkyfunky` 
    FOREIGN KEY (`id`) 
    REFERENCES `alpha`.`ProductsToCategories` (`productid`)  
    ON DELETE CASCADE,  
    ON UPDATE CASCADE) 

ENGINE = InnoDB; 

Répondre

1

Table Vos produits est un peu mal, comme vous n'avez pas besoin de faire référence à quoi que ce soit de lui. références aller dans les « autres » tables, et le point au principal, par exemple:

create table products (
    id int auto_increment, 
    type int, 
    primary key (id) 
); 

create table categories (
    id int auto_increment, 
    name varchar(128), 
    primary key (id) 
) 

create table products_to_categories (
    product_id int references products, 
    category_id int references categories 
); 
+0

Salut Einar, Merci pour votre réponse. Va certainement tester cela, des sons en effet comme ça pourrait être une solution! – Industrial

+0

Une autre pensée que je souhaite avoir une contribution sur. Lorsque la table des produits utilise une clé étrangère, un produit supprimé supprime également la connexion aux catégories créées dans la table "products_to_categories". N'est-ce pas la meilleure façon d'utiliser foreign_keys? Je veux dire, si j'ai supprimé la ligne dans products_to_categories, je ne voudrais pas que le produit soit supprimé? – Industrial

+2

Il s'agit essentiellement d'une suppression en cascade. Lorsqu'un produit est supprimé, les entrées correspondantes dans "products_to_categories" seront supprimées. La clé étrangère doit être déclarée bien sûr dans "products_to_categories" avec une suppression en cascade. Vous avez déjà ajouté la suppression CASCADE. Il suffit de déplacer la clé étrangère vers les "products_to_categories". –

2

Vous ne pouvez pas supprimer une ligne de la table parent alors qu'il est une référence clé étrangère à elle d'une table des enfants. De plus, vous ne pouvez pas insérer/mettre à jour dans la table enfant avec des identifiants invalides dans la colonne clé étrangère. Edit: La clause "CONSTRAINT funkyfunky FOREIGN KEY (id)" doit être déclarée dans le tableau "ProductsToCategories" et non dans le tableau "Products", car "ProductsToCategories" fait référence à "Products" et non à l'inverse.

+0

est ici la chose que j'ai un parent et une table enfant les deux sont frais vide Quand je fais un insert à la table des parents... – Industrial

+3

Etrange Êtes-vous sûr d'avoir correctement configuré la clé étrangère? Je pense que vous avez inversé la table enfant et la table parente lors de la création de la clé étrangère –

+0

Oui, y Vous avez inversé les tables. Voir ma modification. –

1

Une clé étrangère applique une relation valide entre les lignes de deux tables. Afin de pouvoir insérer une ligne dans une table contenant une clé étrangère, il doit y avoir une ligne dans la table référencée contenant cette clé ou l'insertion échouera. De même avec delete, vous ne pouvez pas supprimer la ligne dans la table référencée tant qu'il y a encore des lignes dans la table avec la clé étrangère qui la référence toujours. Cela empêche de se retrouver avec des lignes dans la table dépendante qui ont des données, mais n'ont pas de lignes associées dans la table référencée, c'est-à-dire, une violation de l'intégrité référentielle.

4

Votre insertion échoue car la clé étrangère de la ligne que vous insérez ne correspond pas à une clé valide dans la table de contraintes. Par exemple:

Supposons que vous avez ces deux tables:

Employees 
---------------------------- 
EmpID | Name 
---------------------------- 
0  | John 
1  | Jane 

OfficeAssignments 
---------------------------- 
OfficeID | EmpID 
---------------------------- 
0  | 0 
1  | 1 

Si vous avez une contrainte de clé étrangère sur OfficeAssignments.EmpID -> Employees.EmpID, et vous essayez d'exécuter:

INSERT INTO OfficeAssignments (OfficeID, EmpID) VALUES (2,2) 

La déclaration échouera car il n'y a aucune entrée dans la table Employees avec un EmpID de 2.

Les contraintes sont conçues pour assurer que votre t dépend Vous pouvez toujours avoir des données valides en ce qui concerne la table parent - dans cet exemple, vous n'aurez jamais un bureau qui est répertorié comme assigné à un employé qui n'existe pas dans le système, soit parce qu'ils n'ont jamais existé (comme dans ce cas) ou parce qu'ils ont été supprimés (car la contrainte empêchera la suppression de l'enregistrement de l'employé jusqu'à ce que l'enregistrement d'affectation de bureau ait été supprimé en premier).

Editer: Maintenant que vous avez posté la contrainte, il semble qu'elle puisse être configurée à rebours. En plaçant la contrainte dans la définition de la table Products, vous en faites l'enfant et ProductsToCategories le parent. La contrainte que vous avez écrite peut être lue comme "un produit doit être affecté à une catégorie avant de pouvoir être créé". Je soupçonne que ce que vous vouliez dire est l'inverse: "Un produit doit être créé avant de pouvoir être affecté à une catégorie."Pour obtenir ce résultat, vous devez placer la contrainte sur la table ProductsToCategories, définissant la clé étrangère productid et référencement Products.id.

+0

Mais il dit que l'insertion dans la table parent (dans votre exemple employés) échoue. Il est impossible d'échouer si la clé étrangère est correctement configurée. –

+1

Juste remarqué que (quand j'ai commencé à écrire le poste que le commentaire n'était pas encore en place). Je suis d'accord avec votre réponse, il semble que la contrainte soit établie à l'envers. –

+0

Salut! Mise à jour de mon premier post pour clarifier les choses un peu! – Industrial

Questions connexes