415 votes

Ajouter une clé étrangère à une table existante

Je veux ajouter une clé étrangère à une table appelée "katalog".

ALTER TABLE katalog 
ADD CONSTRAINT `fk_katalog_sprache` 
FOREIGN KEY (`Sprache`)
REFERENCES `Sprache` (`ID`)
ON DELETE SET NULL
ON UPDATE SET NULL;

Lorsque j'essaie de le faire, j'obtiens ce message d'erreur :

Error Code: 1005. Can't create table 'mytable.#sql-7fb1_7d3a' (errno: 150)

Erreur dans le statut INNODB :

120405 14:02:57 Erreur dans la contrainte de clé étrangère de la table matable.#sql-7fb1_7d3a :

FOREIGN KEY (`Sprache`)
REFERENCES `Sprache` (`ID`)
ON DELETE SET NULL
ON UPDATE SET NULL:
Cannot resolve table name close to:
(`ID`)
ON DELETE SET NULL
ON UPDATE SET NULL

Lorsque j'utilise cette requête, elle fonctionne, mais avec une action "on delete" erronée :

ALTER TABLE `katalog` 
ADD FOREIGN KEY (`Sprache` ) REFERENCES `sprache` (`ID` )

Les deux tables sont InnoDB et les deux champs sont "INT(11) not null". J'utilise MySQL 5.1.61. J'essaie de lancer cette ALTER Query avec MySQL Workbench (la plus récente) sur un MacBook Pro.

Table Créer des déclarations :

CREATE TABLE `katalog` (
`ID` int(11) unsigned NOT NULL AUTO_INCREMENT,
`Name` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`AnzahlSeiten` int(4) unsigned NOT NULL,
`Sprache` int(11) NOT NULL,
PRIMARY KEY (`ID`),
UNIQUE KEY `katalogname_uq` (`Name`)
 ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=DYNAMIC$$

CREATE TABLE `sprache` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
 `Bezeichnung` varchar(45) NOT NULL,
 PRIMARY KEY (`ID`),
 UNIQUE KEY `Bezeichnung_UNIQUE` (`Bezeichnung`),
KEY `ix_sprache_id` (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8

1 votes

Puisque vous n'avez pas posté la sortie de SHOW CREATE TABLE Je ne peux que demander : le nom de la colonne est-il vraiment ID, en majuscules ?

0 votes

Eh bien, c'est plus facile à repérer maintenant - katalog a int(11) unsigned . sprache n'a pas le usigned partie, donc deux colonnes ne sont pas les mêmes.

0 votes

Voulez-vous dire que les deux champs primaires doivent avoir le même type de données ?

697voto

iltaf khalid Points 941

Pour ajouter une clé étrangère (grade_id) à une table existante (users), suivez les étapes suivantes :

ALTER TABLE users ADD grade_id SMALLINT UNSIGNED NOT NULL DEFAULT 0;
ALTER TABLE users ADD CONSTRAINT fk_grade_id FOREIGN KEY (grade_id) REFERENCES grades(id);

14 votes

Les raisons m'aident à comprendre et à me souvenir. C'est parce que vous ne pouvez pas ajouter une clé étrangère à un champ non signé, correct ?

12 votes

@PixMach, la réponse est non. Vous pouvez avoir des entiers signés comme clés étrangères. Comme N.B. l'a noté dans la question, le type et le signe des champs doivent correspondre. Ainsi, si votre clé primaire dans la table de consultation est UNSIGNED, alors le champ de la clé étrangère doit également être UNSIGNED. Si le champ de la clé primaire est SIGNÉ, alors le champ de la clé étrangère doit également être signé. Pensez-y de cette façon : quelle que soit la définition de la colonne dans une table dans un SHOW CREATE TABLE, elle doit avoir la même définition dans l'autre table.

1 votes

Notez que cela pourrait également être fait avec une seule requête (ce qui pourrait être mieux en cas d'échec, etc.).

95voto

Sagar Panchal Points 1535

Utilisez simplement cette requête, je l'ai essayée selon mon scénario et elle fonctionne bien.

ALTER TABLE katalog ADD FOREIGN KEY (`Sprache`) REFERENCES Sprache(`ID`);

3 votes

Vous devez ajouter un avertissement/une clause de non-responsabilité indiquant que cela créera un nom de contrainte pour vous. Ce qui aura de graves conséquences lors des migrations de bases de données, lorsque vous voudrez modifier vos contraintes. C'est toujours une bonne pratique de nommer les choses.

18voto

Bill Points 51
FOREIGN KEY (`Sprache`)
REFERENCES `Sprache` (`ID`)
ON DELETE SET NULL
ON UPDATE SET NULL;

Mais votre table l'a fait :

CREATE TABLE `katalog` (
`Sprache` int(11) NOT NULL,

Il cant mettre la colonne Sprache à NULL car elle est définie comme NOT NULL.

16voto

ZZ-bb Points 1336

Vérifiez ce lien. Il m'a aidé avec errno 150 : http://verysimple.com/2006/10/22/mysql-error-number-1005-cant-create-table-mydbsql-328_45frm-errno-150/

Deux choses me viennent à l'esprit.

  • Votre index de clé étrangère est-il un nom unique dans toute la base de données (n° 3 dans la liste) ?
  • Essayez-vous d'attribuer à la table PK la valeur NULL lors de la mise à jour (n° 5 dans la liste) ?

Je suppose que le problème se situe au niveau du set NULL lors de la mise à jour (si mon cerveau n'est pas à l'envers aujourd'hui comme il l'est si souvent...).

Edit : J'ai manqué les commentaires sur votre message original. Les colonnes int non signées/non non signées ont peut-être résolu votre cas. J'espère que mon lien aidera quelqu'un à l'avenir.

4voto

Maksym Polshcha Points 4712

Lorsque vous ajoutez une contrainte de clé étrangère à une table en utilisant ALTER TABLE, n'oubliez pas de créer d'abord les index requis.

  1. Créer un index
  2. Modifier la table

0 votes

J'ai créé un index pour les deux. Lorsque j'essaie de l'exécuter, j'obtiens le même message d'erreur que précédemment. Lorsque je supprime la partie "on delete on update", cela fonctionne mais avec la mauvaise action "on delete" ;)

0 votes

@frgtv10 le plus probable est que les données des tables entrent en conflit avec "on delete".

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X