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

324

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, je reçois ce message d'erreur:

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

Erreur dans l'état INNODB:

120405 14:02:57 Erreur dans la contrainte de clé étrangère de la table mytable. # 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, cela fonctionne, mais avec une mauvaise action "on delete":

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

Les deux tables sont InnoDB et les deux champs sont "INT (11) non null". J'utilise MySQL 5.1.61. Essayer de lancer cette requête ALTER avec MySQL Workbench (le plus récent) sur un MacBook Pro.

Tableau Créer des instructions:

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
frgtv10
la source
1
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?
NB
Eh bien, c'est plus facile à repérer maintenant - kataloga int(11) unsigned. sprachen'a pas la usignedpartie, donc deux colonnes ne sont pas identiques.
NB
Voulez-vous dire que les deux champs principaux doivent être du même type de données?
frgtv10
2
C'est le problème avec votre conception: d'abord, vous faites référence à deux auto_incrementcolonnes, ce qui est mauvais. En outre, le manuel de MySQL dit: Corresponding columns in the foreign key and the referenced key must have similar internal data types inside InnoDB so that they can be compared without a type conversion. The size and sign of integer types must be the same. The length of string types need not be the same. For nonbinary (character) string columns, the character set and collation must be the same.. Par conséquent, oui, un type de données similaire et le même signe.
NB
2
Je ne fais pas référence à deux champs auto_increment. katalog.Sprache (pas auto) -> sprache.ID (auto)
frgtv10

Réponses:

560

Pour ajouter une clé étrangère (grade_id) à une table existante (utilisateurs), procédez comme suit:

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);
iltaf khalid
la source
12
Les raisons m'aident à comprendre et à me souvenir. Cela est dû au fait que vous ne pouvez pas ajouter de clé étrangère à un champ non signé, n'est-ce pas?
PixMach
8
@PixMach, la réponse est non. Vous pouvez avoir des entiers signés comme clés étrangères. Comme NB l'a noté sur la question, le type et le signe des champs doivent correspondre. Donc, si votre clé primaire dans la table de recherche est UNSIGNED, le champ de clé étrangère doit également être UNSIGNED. Si le champ de clé primaire est SIGNÉ, le champ de clé étrangère doit également être signé. Pensez-y de cette façon: quelle que soit la colonne d'une table définie comme dans un SHOW CREATE TABLE, elle doit avoir la même définition dans l'autre table.
Ben Keene
1
Notez que cela peut également être fait avec une seule requête (peut-être mieux en cas d'échec, etc.)
Stijn de Witt
6
J'ai dû exécuter "SET FOREIGN_KEY_CHECKS = 0;" avant d'exécuter la commande ADD CONSTRAINT ou SQL se plaindrait "Impossible d'ajouter ou de mettre à jour une ligne enfant: une contrainte de clé étrangère échoue".
Erin Geyer
2
Ne vous contentez pas d' exécuter "SET FOREIGN_KEY_CHECKS = 0;" si vous obtenez l'erreur "une contrainte de clé étrangère échoue", vous avez évidemment de mauvaises données que vous devez corriger, sinon vous obtiendrez de plus gros problèmes sur toute la ligne.
MazeChaZer
72

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

ALTER TABLE katalog ADD FOREIGN KEY (`Sprache`) REFERENCES Sprache(`ID`);
SagarPPanchal
la source
25

Étapes simples ...

ALTER TABLE t_name1 ADD FOREIGN KEY (column_name) REFERENCES t_name2(column_name)
Amjath Khan
la source
15

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

Au sommet de ma tête, deux choses me viennent à l'esprit.

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

Je suppose que le problème est avec l'ensemble NULL lors de la mise à jour (si mon cerveau n'est pas à l'envers aujourd'hui comme c'est souvent le cas ...).

Edit: j'ai raté les commentaires sur votre post d'origine. Les colonnes int non signées / non signées peuvent résoudre votre cas. J'espère que mon lien aide quelqu'un dans la pensée future.

ZZ-bb
la source
13
FOREIGN KEY (`Sprache`)
REFERENCES `Sprache` (`ID`)
ON DELETE SET NULL
ON UPDATE SET NULL;

Mais votre table a:

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

Il ne peut pas définir la colonne Sprache sur NULL car elle est définie comme NOT NULL.

Facture
la source
5

MySQL exécutera cette requête:

ALTER TABLE `db`.`table1`
ADD COLUMN `col_table2_fk` INT UNSIGNED NULL,
ADD INDEX `col_table2_fk_idx` (`col_table2_fk` ASC),
ADD CONSTRAINT `col_table2_fk1`
FOREIGN KEY (`col_table2_fk`)
REFERENCES `db`.`table2` (`table2_id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION;

À votre santé!

akelec
la source
5

Comment réparer Error Code: 1005. Can't create table 'mytable.#sql-7fb1_7d3a' (errno: 150) in mysql.

  1. modifier votre table et y ajouter un index ..

    ALTER TABLE users ADD INDEX index_name (index_column)
  2. Ajoutez maintenant la contrainte

    ALTER TABLE foreign_key_table
    ADD CONSTRAINT foreign_key_name FOREIGN KEY (foreign_key_column)
    REFERENCES primary_key_table (primary_key_column) ON DELETE NO ACTION
    ON UPDATE CASCADE;

Notez que si vous n'ajoutez pas d'index, cela ne fonctionnera pas.

Après avoir lutté avec elle pendant environ 6 heures, j'ai trouvé la solution, j'espère que cela sauvera une âme.

Kwed
la source
4

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

  1. Créer un index
  2. Modifier table
Maksym Polshcha
la source
J'ai créé un index pour les deux. Lorsque j'essaie de courir, j'obtiens le même message d'erreur qu'auparavant. Quand je rejette la partie "on delete on update" ça marche mais avec la mauvaise action "on delete";)
frgtv10
@ frgtv10 le plus probable que les données des tables entrent en conflit avec "lors de la suppression".
Maksym Polshcha
3

essayez tout en une seule requête

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

cela se produit essentiellement parce que vos tables sont dans deux jeux de caractères différents. par exemple, une table créée dans charset = utf-8 et d'autres tables sont créées dans CHARSET = latin1 afin que vous souhaitiez pouvoir ajouter une clé foriegn à ces tables. utilisez le même jeu de caractères dans les deux tableaux, vous pourrez alors ajouter des clés foriegn. erreur 1005 foriegn contrainte de clé incorrectement formée peut résoudre à partir de ce

Pumudu Fernando
la source
0

j'ai traversé le même problème. Dans mon cas, le tableau contient déjà des données et il y avait des clés dans ce tableau qui n'étaient pas présentes dans le tableau de référence. J'ai donc dû supprimer ces lignes qui ne respectaient pas les contraintes et tout fonctionnait.

Henrique
la source
0

étape 1: exécutez ce script

SET FOREIGN_KEY_CHECKS=0;

étape 2: ajouter une colonne

ALTER TABLE mileage_unit ADD COLUMN COMPANY_ID BIGINT(20) NOT NULL

étape 3: ajouter une clé étrangère à la colonne ajoutée

ALTER TABLE mileage_unit
ADD FOREIGN KEY (COMPANY_ID) REFERENCES company_mst(COMPANY_ID);

étape 4: exécutez ce script

SET FOREIGN_KEY_CHECKS=1;
rushikesh satpute
la source
-1
 ALTER TABLE TABLENAME ADD FOREIGN KEY (Column Name) REFERENCES TableName(column name)

Exemple:-

ALTER TABLE Department ADD FOREIGN KEY (EmployeeId) REFERENCES Employee(EmployeeId)
Harshitha Nagabhushana
la source
1
Veuillez ajouter des explications à votre code afin que d'autres puissent en tirer des leçons
Nico Haase