J'essaie de créer une table dans MySQL avec deux clés étrangères, qui référencent les clés primaires dans 2 autres tables, mais j'obtiens une erreur errno: 150 et cela ne créera pas la table.
Voici le SQL pour les 3 tables:
CREATE TABLE role_groups (
`role_group_id` int(11) NOT NULL `AUTO_INCREMENT`,
`name` varchar(20),
`description` varchar(200),
PRIMARY KEY (`role_group_id`)
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `roles` (
`role_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50),
`description` varchar(200),
PRIMARY KEY (`role_id`)
) ENGINE=InnoDB;
create table role_map (
`role_map_id` int not null `auto_increment`,
`role_id` int not null,
`role_group_id` int not null,
primary key(`role_map_id`),
foreign key(`role_id`) references roles(`role_id`),
foreign key(`role_group_id`) references role_groups(`role_group_id`)
) engine=InnoDB;
Toute aide serait grandement appréciée.
mysql
foreign-keys
mysql-error-150
Bill Karwin
la source
la source
auto_increment
? Ce n'est pas valable. Auto_increment est un mot-clé, pas un identifiant.Réponses:
J'ai eu le même problème avec
ALTER TABLE ADD FOREIGN KEY
.Après une heure, j'ai trouvé que ces conditions doivent être remplies pour ne pas obtenir l'erreur 150:
La table Parent doit exister avant que vous ne définissiez une clé étrangère pour la référencer. Vous devez définir les tables dans le bon ordre: la table parent d'abord, puis la table enfant. Si les deux tables se réfèrent l'une à l'autre, vous devez créer une table sans contraintes FK, puis créer la deuxième table, puis ajouter la contrainte FK à la première table avec
ALTER TABLE
.Les deux tables doivent toutes deux prendre en charge les contraintes de clé étrangère, c'est-à-dire
ENGINE=InnoDB
. Les autres moteurs de stockage ignorent silencieusement les définitions de clé étrangère, ils ne renvoient donc aucune erreur ou avertissement, mais la contrainte FK n'est pas enregistrée.Les colonnes référencées dans la table Parent doivent être les colonnes les plus à gauche d'une clé. Idéal si la clé du parent est
PRIMARY KEY
ouUNIQUE KEY
.La définition FK doit référencer la ou les colonnes PK dans le même ordre que la définition PK. Par exemple, si le FK
REFERENCES Parent(a,b,c)
alors le PK du parent ne doit pas être défini sur les colonnes dans l'ordre(a,c,b)
.La ou les colonnes PK de la table Parent doivent être du même type de données que la ou les colonnes FK de la table Child. Par exemple, si une colonne PK de la table Parent est
UNSIGNED
, veillez à définirUNSIGNED
pour la colonne correspondante dans le champ Table enfant.Exception: la longueur des chaînes peut être différente. Par exemple,
VARCHAR(10)
peut référencerVARCHAR(20)
ou vice versa.Toute colonne FK de type chaîne doit avoir le même jeu de caractères et le même classement que la ou les colonnes PK correspondantes.
S'il existe déjà des données dans la table enfant, chaque valeur de la ou des colonnes FK doit correspondre à une valeur de la ou des colonnes PK de la table parent. Vérifiez cela avec une requête comme:
Cela doit renvoyer zéro (0) valeurs sans correspondance. De toute évidence, cette requête est un exemple générique; vous devez remplacer vos noms de table et de colonne.
Ni la table Parent ni la table Child ne peuvent être une
TEMPORARY
table.Ni la table Parent ni la table Child ne peuvent être une
PARTITIONED
table.Si vous déclarez un FK avec l'
ON DELETE SET NULL
option, la ou les colonnes FK doivent être Nullable.Si vous déclarez un nom de contrainte pour une clé étrangère, le nom de contrainte doit être unique dans tout le schéma, et pas uniquement dans la table dans laquelle la contrainte est définie. Deux tables peuvent ne pas avoir leur propre contrainte avec le même nom.
S'il y a d'autres FK dans d'autres tables pointant sur le même champ pour lequel vous essayez de créer le nouveau FK, et qu'ils sont mal formés (c'est-à-dire un classement différent), ils devront d'abord être cohérents. Cela peut être le résultat de changements passés où a
SET FOREIGN_KEY_CHECKS = 0;
été utilisé avec une relation incohérente définie par erreur. Voir la réponse de @ andrewdotn ci-dessous pour savoir comment identifier ces problèmes de FK.J'espère que cela t'aides.
la source
int(11) unsigned NOT NULL
vsint(11) NOT NULL
.ON DELETE
règle de votre CONSTRAINT est,SET NULL
assurez-vous que la clé étrangère peut être NULL! J'ai passé 30 minutes à lire cette réponse encore et encore, en m'assurant que mes tables remplissaient les conditions mais en obtenant toujours l'erreur 150. Ensuite, j'ai remarqué que mon FK était un champ NOT NULL, ce qui signifie que la règle était impossible à appliquer.Le message générique "errno 150" de MySQL " signifie qu'une contrainte de clé étrangère n'a pas été correctement formée ." Comme vous le savez probablement déjà si vous lisez cette page, le message d'erreur générique «errno: 150» est vraiment inutile. Toutefois:
Vous pouvez obtenir le message d'erreur réel en exécutant
SHOW ENGINE INNODB STATUS;
et en recherchantLATEST FOREIGN KEY ERROR
dans la sortie.Par exemple, cette tentative de créer une contrainte de clé étrangère:
échoue avec l'erreur
Can't create table 'test.t2' (errno: 150)
. Cela ne dit rien d'utile à personne si ce n'est que c'est un problème de clé étrangère. Mais courezSHOW ENGINE INNODB STATUS;
et il dira:Il dit que le problème est qu'il ne trouve pas d'index.
SHOW INDEX FROM t1
montre qu'il n'y a pas du tout d'index pour tablet1
. Corrigez cela, par exemple, en définissant une clé primaire surt1
, et la contrainte de clé étrangère sera créée avec succès.la source
SHOW ENGINE INNODB STATUS
m'a aidé à identifier immédiatement un problème que j'avais essayé de diagnostiquer pendant près d'une heure. Merci.SET FOREIGN_KEY_CHECKS = 0;
lors d'une importation / modification malformée à un moment ou un autre. Grande aide, merci.Assurez-vous que les propriétés des deux champs que vous essayez de lier à une contrainte sont exactement les mêmes.
Souvent, la propriété «non signé» sur une colonne ID vous surprendra.
la source
Quel est l'état actuel de votre base de données lorsque vous exécutez ce script? Est-ce complètement vide? Votre SQL fonctionne bien pour moi lors de la création d'une base de données à partir de zéro, mais errno 150 a généralement à voir avec la suppression et la recréation de tables faisant partie d'une clé étrangère. J'ai l'impression que vous ne travaillez pas avec une base de données 100% fraîche et nouvelle.
Si vous faites une erreur lors de la "source" de votre fichier SQL, vous devriez pouvoir exécuter la commande "SHOW ENGINE INNODB STATUS" à partir de l'invite MySQL immédiatement après la commande "source" pour voir des informations d'erreur plus détaillées.
Vous pouvez également consulter la saisie manuelle:
la source
Pour les personnes qui consultent ce fil avec le même problème:
Il y a de nombreuses raisons pour obtenir des erreurs comme celle-ci. Pour une liste assez complète des causes et des solutions des erreurs de clé étrangère dans MySQL (y compris celles discutées ici), consultez ce lien:
Erreurs de clé étrangère MySQL et Errno 150
la source
Pour les autres qui trouvent cette entrée SO via Google: assurez-vous que vous n'essayez pas d'effectuer une action SET NULL sur une colonne de clé étrangère (à être) définie comme "NOT NULL". Cela a causé une grande frustration jusqu'à ce que je me souvienne de faire un CHECK ENGINE INNODB STATUS.
la source
Ce n'est certainement pas le cas, mais j'ai trouvé cette erreur assez courante et peu évidente. La cible d'un
FOREIGN KEY
pourrait ne pas l'êtrePRIMARY KEY
. La réponse qui me devient utile est:Une FOREIGN KEY doit toujours être pointée vers un champ vrai PRIMARY KEY d'une autre table.
la source
Comme indiqué par @andrewdotn, le meilleur moyen est de voir l'erreur détaillée (
SHOW ENGINE INNODB STATUS;
) au lieu d'un simple code d'erreur.L'une des raisons pourrait être qu'un index existe déjà avec le même nom, peut-être dans une autre table. En pratique, je recommande de préfixer le nom de la table avant le nom de l'index pour éviter de telles collisions. par exemple au lieu d'
idx_userId
utiliseridx_userActionMapping_userId
.la source
Veuillez d'abord vous assurer que
J'ai eu le même problème et je l'ai résolu. J'avais INT non signé pour un champ et juste un entier pour un autre champ.
la source
Conseil utile, utilisez
SHOW WARNINGS;
après avoir essayé votreCREATE
requête et vous recevrez l'erreur ainsi que l'avertissement plus détaillé:Alors dans ce cas, il est temps de recréer ma table!
la source
Cela se produit généralement lorsque vous essayez de créer un fichier dans une base de données existante. Supprimez d'abord toutes les tables (ou la base de données elle-même). Et puis le fichier source avec
SET foreign_key_checks = 0;
au début etSET foreign_key_checks = 1;
à la fin.la source
J'ai trouvé une autre raison pour laquelle cela échoue ... les noms de table sensibles à la casse.
Pour cette définition de table
Cette définition de table fonctionne
alors que celui-ci échoue
Le fait qu'il a fonctionné sous Windows et a échoué sous Unix m'a pris quelques heures à comprendre. J'espère que cela aide quelqu'un d'autre.
la source
MySQL Workbench 6.3 pour Mac OS.
Problème: erreur n ° 150 sur la table X lors de la tentative de Forward Engineering sur un diagramme DB, 20 sur 21 ont réussi, 1 échoué. Si les FK de la table X ont été supprimés, l'erreur a été déplacée vers une table différente qui n'échouait pas auparavant.
J'ai changé le moteur de toutes les tables en myISAM et cela a très bien fonctionné.
la source
Vérifiez également que vous n'opérez pas accidentellement sur la mauvaise base de données. Cette erreur se produit si la table étrangère n'existe pas. Pourquoi MySQL doit-il être si cryptique?
la source
Assurez-vous que les clés étrangères ne sont pas répertoriées comme uniques dans le parent. J'ai eu ce même problème et je l'ai résolu en le délimitant comme n'étant pas unique.
la source
Dans mon cas, cela était dû au fait que le champ qui était un champ de clé étrangère avait un nom trop long, c'est-à-dire.
foreign key (some_other_table_with_long_name_id)
. Essayez qc plus court. Le message d'erreur est un peu trompeur dans ce cas.De plus, comme @Jon l'a mentionné précédemment, les définitions de champ doivent être les mêmes (attention au
unsigned
sous-type).la source
(Notes latérales trop grosses pour un commentaire)
Il n'y a pas besoin d'un
AUTO_INCREMENT
identifiant dans une table de mappage; débarrassez-vous-en.Remplacez le
PRIMARY KEY
par(role_id, role_group_id)
(dans l'un ou l'autre ordre). Cela rendra les accès plus rapides.Puisque vous souhaitez probablement mapper les deux directions, ajoutez également un
INDEX
avec ces deux colonnes dans l'ordre opposé. (Il n'est pas nécessaire de le faireUNIQUE
.)Plus de conseils: http://mysql.rjweb.org/doc.php/index_cookbook_mysql#speeding_up_wp_postmeta
la source
Lorsque la contrainte de clé étrangère est basée sur le
varchar
type, en plus de la liste fournie parmarv-el
la colonne cible, elle doit avoir une contrainte unique.la source
exécutez la ligne ci-dessous avant de créer la table: SET FOREIGN_KEY_CHECKS = 0;
L'option FOREIGN_KEY_CHECKS spécifie s'il faut vérifier ou non les contraintes de clé étrangère pour les tables InnoDB.
- Spécifiez pour vérifier les contraintes de clé étrangère (c'est la valeur par défaut)
- Ne pas vérifier les contraintes de clé étrangère
SET FOREIGN_KEY_CHECKS = 0;
Quand l'utiliser: La désactivation temporaire des contraintes référentielles (définissez FOREIGN_KEY_CHECKS sur 0) est utile lorsque vous devez recréer les tables et charger des données dans n'importe quel ordre parent-enfant
la source
J'ai rencontré le même problème, mais je vérifie que je n'avais pas la table parent. Je viens donc de modifier la migration parentale devant la migration enfant. Simplement fais-le.
la source