MySQL: Impossible de créer la table (errno: 150)

156

J'essaie d'importer un fichier .sql et son échec lors de la création de tables.

Voici la requête qui échoue:

CREATE TABLE `data` (
`id` int(10) unsigned NOT NULL,
`name` varchar(100) NOT NULL,
`value` varchar(15) NOT NULL,
UNIQUE KEY `id` (`id`,`name`),
CONSTRAINT `data_ibfk_1` FOREIGN KEY (`id`) REFERENCES `keywords` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;    

J'ai exporté le .sql de la même base de données, j'ai supprimé toutes les tables et maintenant j'essaye de l'importer, pourquoi échoue-t-il?

MySQL: impossible de créer la table './dbname/data.frm' (errno: 150)

gtilx
la source
1
Pour l'essentiel de toutes les causes de cette erreur, voici une ressource exhaustive sur les causes de l'errno 150 (et de l'errno 121 / autres erreurs de clé étrangère) dans MySQL.
John Smith
21
J'ai trouvé que les colonnes doivent être identiques (même le drapeau non signé doit correspondre).
Justin Skiles
3
@JohnSmith ... où?
Charles Wood
3
Je suggère de lire ce billet de blog qui répertorie 10 causes possibles: verysimple.com/2006/10/22/…
Mark Amery
@CharlesWood: " John Smith ... vu le 6 avril 13 à 19:29 ", soit environ trois mois avant votre commentaire. J'ai peur qu'un mystère de «où» ne soit révélé avant la fin de ce monde morne! :>
trejder

Réponses:

167

À partir de la documentation MySQL - FOREIGN KEY Constraints :

Si vous recréez une table qui a été supprimée, elle doit avoir une définition conforme aux contraintes de clé étrangère qui la référencent. Il doit avoir les noms et types de colonne corrects, et il doit avoir des index sur les clés référencées, comme indiqué précédemment. Si ceux-ci ne sont pas satisfaits, MySQL renvoie l'erreur 1005 et fait référence à l'erreur 150 dans le message d'erreur, ce qui signifie qu'une contrainte de clé étrangère n'a pas été correctement formée. De même, si un ALTER TABLE échoue en raison de l'erreur 150, cela signifie qu'une définition de clé étrangère serait mal formée pour la table modifiée.

Poneys OMG
la source
1
Deux colonnes d'une table peuvent-elles référencer une colonne d'une autre table, où il s'agit de PK?
Eugene
1
@Eugene: Chacune des deux colonnes peut avoir une relation de clé étrangère avec le PK dans une autre table - pas les deux colonnes comme une seule relation de clé étrangère.
OMG Ponies
1
@OMGPonies: Merci d'avoir répondu à cette question! .. Je la cherchais ... J'ai aussi posé une question ici stackoverflow.com/questions/13487010/… .... Bien que j'ai quelques bonnes réponses mais je veux être conforme Whether its possible to write Nested Query for my problem? .. Je vous demanderais de me répondre aussi!
Grijesh Chauhan
19
Mon erreur était que la table principale avait MyISAM et le moteur InnoDB de la table enfant. Le script create.sql actuel utilisait InnoDB pour toutes les tables, mais j'avais une très très ancienne installation où le premier script utilisait MyISAM.
Whome
2
@Whome - Oui, j'ai rencontré le même problème ici.
aroth
96

L'erreur 150 signifie que vous avez un problème avec votre clé étrangère. Peut-être que la clé de la table étrangère n'est pas exactement du même type?

Dan McGrath
la source
15
Merci :) pour moi, les types de données sont INT mais l'un non signé tandis que l'autre ne l'est pas
Anh Nguyen
6
Je rencontre souvent BIGINTvs INTlors de l'utilisation de générateurs de schéma.
Xeoncross
J'ai rencontré le même problème lorsque la clé étrangère n'est pas une valeur INT. La colonne doit être UNIQUE lorsque la clé étrangère y fait référence.
PhatHV
62

Vous pouvez obtenir le message d'erreur réel en exécutant SHOW ENGINE INNODB STATUS;et en recherchant LATEST FOREIGN KEY ERRORdans la sortie.

Source: réponse d'un autre utilisateur à une question similaire

Denilson Sá Maia
la source
7
C'est en fait très utile. Il vous indique l'erreur exacte.
Csongor Fagyal
Merci. C'est dommage que MySQL Workbench ne s'en serve pas.
scipilot
Impressionnant. C'est tellement utile. Vous indique l'erreur exacte. Le mien était d'avoir rendu la colonne NULLABLE mais avait mis "on delete set null". Merci beaucoup.
Abhishek Saini
Si vous avez des privilèges sur votre serveur :(
Christopher Smit
30

Les types de données doivent correspondre exactement. Si vous utilisez des types varchar, les tables doivent utiliser le même classement.

Esben Skov Pedersen
la source
4
Merci pour le peu de collation.
arahant
25

Je pense que toutes ces réponses, bien que correctes, induisent en erreur la question.

La vraie réponse est la suivante avant de démarrer une restauration, si vous restaurez un fichier de vidage avec des clés étrangères:

SET FOREIGN_KEY_CHECKS=0;

car naturellement la restauration créera des contraintes avant même que la table étrangère n'existe.

Colin
la source
Cela n'a pas fonctionné pour moi, cela donne toujours l'erreur. Des idées?
Joseph Astrahan
24

Dans certains cas, vous pouvez rencontrer ce message d'erreur s'il existe différents moteurs entre les tables associées. Par exemple, une table peut utiliser InnoDB tandis que l'autre utilise MyISAM. Les deux doivent être identiques

pi.
la source
Merci - c'était mon problème.
scipilot
C'était mon problème. Merci
thed0ctor
Cela peut arriver si vous avez créé un fichier sql de la table innodb en utilisant mysqldump et qu'ils ont été exportés en tant que myisam talbes à la place.
Amado Martinez
11

Erreur no. 150 signifie un échec de contrainte de clé étrangère. Vous créez probablement cette table avant la table dont dépend la clé étrangère (table keywords). Créez d'abord cette table et cela devrait fonctionner correctement.

Si ce n'est pas le cas, supprimez l'instruction de clé étrangère et ajoutez-la après la création de la table - vous obtiendrez un message d'erreur plus significatif concernant l'échec de la contrainte spécifique.

Eran Galperin
la source
10

Il y a pas mal de choses qui peuvent causer l'erreur 150, donc pour les personnes qui recherchent ce sujet, voici ce que je pense être une liste presque exhaustive (source Causes de Errno 150 ):

Pour l'errno 150 ou l'errno 121, en tapant simplement SHOW ENGINE INNODB STATUS, il y a une section appelée "LATEST FOREIGN KEY ERROR". En dessous, cela vous donnera un message d'erreur très utile, qui vous dira généralement tout de suite quel est le problème. Vous avez besoin de privilèges SUPER pour l'exécuter, donc si vous ne l'avez pas, vous devrez simplement tester les scénarios suivants.

1) Les types de données ne correspondent pas: les types de colonnes doivent être les mêmes

2) Colonnes parentes non indexées (ou indexées dans le mauvais ordre)

3) Les classements de colonnes ne correspondent pas

4) Utilisation de SET NULL sur une colonne NOT NULL

5) Les classements de table ne correspondent pas: même si les classements de colonnes correspondent, sur certaines versions de MySQL, cela peut être un problème.

6) La colonne parent n'existe pas réellement dans la table parent. Vérifiez l'orthographe (et peut-être un espace au début ou à la fin de la colonne)

7) L'un des index de l'une des colonnes est incomplet ou la colonne est trop longue pour un index complet. Notez que MySQL (sauf si vous le modifiez) a une longueur maximale de clé de colonne unique de 767 octets (cela correspond à une colonne UTF varchar (255))

Dans le cas où vous obtenez un numéro d'erreur 121, voici quelques causes:

1) Le nom de la contrainte que vous avez choisi est déjà pris

2) Sur certains systèmes, s'il y a une différence de casse dans votre déclaration et les noms de table. Cela peut vous mordre si vous passez d'un serveur à un autre qui a des règles de gestion des cas différentes.

Juacala
la source
Dans certaines versions, vous obtenez un errno 150 si la table n'est pas innodb, mais dans certaines versions, elle échoue simplement en silence.
juacala
Merci, c'était super: | ------------------------ | DERNIÈRE ERREUR DE CLÉ ÉTRANGÈRE | ------------------------ | Vous avez défini une condition SET NULL via certains des | les colonnes sont définies comme NOT NULL.
Sam Critchley
8

Parfois, MySQL est tout simplement super stupide - je peux comprendre la cause des clés étrangères ... mais dans mon cas, je viens de supprimer toute la base de données et j'obtiens toujours l'erreur ... pourquoi? je veux dire, il n'y a plus de base de données ... et l'utilisateur sql que j'utilise n'a pas accès à d'autres bases de données sur le serveur ... je veux dire, le serveur est "vide" pour l'utilisateur actuel et je reçois toujours cette erreur? Désolé mais je suppose que MySQL me ment ... mais je peux m'en occuper :) Ajoutez simplement ces deux lignes de SQL autour de votre putain de déclaration:

SET FOREIGN_KEY_CHECKS = 0;
# some code that gives you errno: 150
SET FOREIGN_KEY_CHECKS = 1;

Maintenant, le sql devrait être exécuté ... Si vous avez vraiment un problème de clé étrangère, il vous apparaîtrait par la ligne où vous réactiverez les vérifications - cela échouera alors .. mais mon serveur est juste silencieux :)

jebbie
la source
Cela peut entraîner des problèmes s'il existe réellement des différences entre la colonne et la colonne à laquelle elle fait référence. Par exemple. Supposons que la colonne référencée est un varchar (200) et que le référent est varchar (50), alors lorsqu'une cascade est tentée, un comportement étrange peut s'ensuivre. Je n'ai pas rencontré de problème où l'erreur n ° 150 est émise en raison d'une incompatibilité de données.
juacala
Intéressant aperçu @juacala :) C'est drôle pour moi seulement, chaque fois que je suis tombé sur ça, mon approche l'a toujours corrigé ... jusqu'à aujourd'hui au moins: D Mais nous
n'arrêtons
Cela m'a aidé avec un script généré par liquibase. Le script a parfaitement fonctionné sur MySQL> 5.5, mais a échoué pour la version 5.1.
delbertooo
4

Après avoir parcouru les réponses ci-dessus et expérimenté un peu, c'est un moyen efficace de résoudre les erreurs de clé étrangère dans MySQL (1005 - erreur 150).

Pour que la clé étrangère soit correctement créée, tout ce que MySQL demande est:

  • Toutes les clés référencées DOIVENT avoir un index PRIMAIRE ou UNIQUE.
  • La colonne référencée DOIT à nouveau avoir un type de données identique à la colonne référencée.

Répondez à ces exigences et tout ira bien.

Davies Malesi
la source
4

J'ai rencontré cette erreur lorsque j'ai porté l'application Windows sur Linux. Sous Windows, les noms de table de base de données sont insensibles à la casse, et sous Linux, ils le sont, probablement en raison de la différence du système de fichiers. Donc, sur la table Windows Table1est le même que table1, et dans les REFERENCESdeux table1et Table1fonctionne. Sous Linux, lorsque l'application était utilisée table1au lieu de Table1créer la structure de la base de données, j'ai vu l'erreur n ° 150; quand j'ai fait la bonne casse des caractères dans les Table1références, cela a commencé à fonctionner aussi sous Linux. Donc, si rien d'autre ne vous aide, assurez-vous que REFERENCESvous utilisez la casse des caractères correcte dans le nom de la table lorsque vous utilisez Linux.

Vitalii
la source
C'était aussi mon cas! Déplacement du script d'une version non sensible à la casse (OS X) vers une version mysql sensible à la casse (Debian).
mircealungu
3

Changez les moteurs de vos tables, seule innoDB prend en charge les clés étrangères

Lapins
la source
3

Si la table PK est créée dans un CHARSET et que vous créez ensuite une table FK dans un autre CHARSET..alors vous pourriez aussi obtenir cette erreur ... J'ai moi aussi cette erreur, mais après avoir changé le jeu de caractères en PK charset, il a été exécuté sans erreur

create table users
(
------------
-------------
)DEFAULT CHARSET=latin1;


create table Emp
(
---------
---------
---------
FOREIGN KEY (userid) REFERENCES users(id) on update cascade on delete cascade)ENGINE=InnoDB, DEFAULT CHARSET=latin1;
tinku
la source
3

Cette erreur peut se produire si deux tables ont une référence, par exemple, une table est Student et une autre table est Education, et nous voulons que la table Education ait une référence de clé étrangère de la table Student. Dans ce cas, le type de données de colonne pour les deux tables doit être le même, sinon cela générera une erreur.

manzarul haque
la source
3

Dans la plupart des cas, le problème est dû à la différence MOTEUR .Si le parent est créé par InnoDB, les tables référencées supposées être créées par MyISAM et vice versa

Sunil Kumar Mohanty
la source
3

Dans mon cas. J'ai eu des problèmes avec le moteur et le jeu de caractères car mon serveur d'hébergement change les paramètres et mes nouvelles tables étaient MyISAM mais mes anciennes tables sont InnoDB. Juste j'ai changé.

Ignacio Hernández
la source
Cela me convenait, car je modifiais une base de données que je n'avais pas créée.
FonzTech
3

généralement, l'incompatibilité entre la clé étrangère et la clé primaire provoque l'erreur: 150.

La clé étrangère doit avoir le même type de données que la clé primaire . En outre, si la clé primaire n'est pas signée, la clé étrangère doit également être non signée .

Rakesh
la source
3

J'ai eu le même problème. Il était lié à la colonne de la table Collation et jeu de caractères . Assurez-vous que le jeu de caractères et le classement doivent être identiques pour les deux colonnes de deux tables. Si vous souhaitez définir une clé étrangère sur cela. Exemple - Si vous placez une clé étrangère sur la colonne userID de la table userImage référençant la colonne userID de la table users, le classement doit être le même que utf8_general_ci et le jeu de caractères utf8 pour les deux colonnes des tables. Généralement, lorsque vous créez une table, mysql prend ces deux configurations à partir des paramètres du serveur.

Sushilkumar
la source
Pourquoi n'ai-je pas vu ce poiste avant!? J'ai passé une heure à déterminer la cause profonde. C'était le jeu de caractères dans mon cas. Les tables référencées et référencées doivent avoir le même jeu de caractères.
Sujit Joshi
2

Veuillez vous assurer que votre colonne de clé primaire et votre colonne référencée ont les mêmes types de données et attributs (non signé, binaire, zerofill non signé, etc.).

Basit
la source
2

Un cas réel est celui où vous avez utilisé un outil MySQL (Sequel Pro dans mon cas) pour renommer une base de données. Puis créé une base de données avec le même nom.

Cela gardait les contraintes de clé étrangère sur le même nom de base de données, de sorte que la base de données renommée (par exemple, my_db_renamed) avait des contraintes de clé étrangère dans la base de données nouvellement créée (my_db)

Je ne sais pas s'il s'agit d'un bogue dans Sequel Pro, ou si un cas d'utilisation nécessite ce comportement, mais cela m'a coûté la meilleure partie de la matinée: /

chim
la source
2

J'ai eu la même erreur. Dans mon cas, la raison de l'erreur était que j'avais une instruction ON DELETE SET NULL dans la contrainte tandis que le champ sur lequel j'ai mis la contrainte dans sa définition avait une instruction NOT NULL. Autoriser NULL dans le champ a résolu le problème.

Wilbert van Diemen
la source
2

J'ai rencontré ce genre de problème lors de la création de DB à partir du fichier texte.

mysql -uroot -padmin < E:\important\sampdb\createdb.sql
mysql -uroot -padmin sampdb < E:\important\sampdb\create_student.sql
mysql -uroot -padmin sampdb < E:\important\sampdb\create_absence.sql

mysql -uroot -padmin sampdb < E:\important\sampdb\insert_student.sql
mysql -uroot -padmin sampdb < E:\important\sampdb\insert_absence.sql

mysql -uroot -padmin sampdb < E:\important\sampdb\load_student.sql
mysql -uroot -padmin sampdb < E:\important\sampdb\load_absence.sql 

Je viens d'écrire les lignes ci-dessus Create.batet d'exécuter le fichier bat.

Mon erreur est dans l'ordre de séquence d'exécution dans mes fichiers sql. J'ai essayé de créer une table avec une clé primaire et une clé étrangère. Pendant son exécution, il recherchera la table de référence mais les tables n'y sont pas. Il renverra donc ce genre d'erreur.

Si vous créez des tables avec une clé étrangère, vérifiez que les tables de référence sont présentes ou non. Vérifiez également le nom des tables et des champs de référence.

Dharani Dharan
la source
En d'autres termes, vous avez essayé de créer une table avec une clé étrangère pointant vers une autre table qui n'existait pas encore. Créez les tableaux dans le bon ordre pour résoudre le problème.
Vincent
2

J'ai eu un problème similaire, mais le mien était dû au fait que j'ajoutais un nouveau champ à une table existante contenant des données et que le nouveau champ faisait référence à un autre champ de la table parent et avait également la définition de NOT NULL et sans aucune valeur par défaut. - J'ai découvert que les choses ne fonctionnaient pas parce que

  1. Mon nouveau champ devait remplir automatiquement les champs vides avec une valeur de la table parent sur chaque enregistrement, avant que la contrainte puisse être appliquée. Chaque fois que la contrainte est appliquée, elle doit conserver l'intégrité des données de la table. L'implémentation de la contrainte (clé étrangère) mais il y avait des enregistrements de base de données qui n'avaient pas les valeurs de la table parent signifierait que les données sont corrompues, donc MySQL n'imposerait JAMAIS VOTRE CONTRAINTE

Il est important de se rappeler que dans des circonstances normales, si vous planifiez votre base de données bien à l'avance et implémentez des contraintes avant l'insertion de données, ce scénario particulier serait évité

L'approche la plus simple pour éviter ce piège est de

  • Sauvegardez les données de vos tables de base de données
  • Tronquer les données de la table (et les artefacts de table, c'est-à-dire les index, etc.)
  • Appliquer les contraintes
  • Importez vos données

J'espère que ça aidera quelqu'un

chitwarnold
la source
1

Peut - être ceci aidera ? La définition de la colonne de clé primaire doit être exactement la même que celle de la colonne de clé étrangère.

Mukus
la source
1

Assurez-vous que toutes les tables peuvent prendre en charge la clé étrangère - moteur InnoDB

joksy82
la source
1

La colonne de la table PARENT à laquelle vous faites référence à partir de la table enfant doit être unique. Si ce n'est pas le cas, provoque une erreur n ° 150.

Dila Ram Gurung
la source
il vaudrait probablement la peine que vous ajoutiez un peu plus de détails - par exemple les noms de colonnes et de tables spécifiques
Jonathan
1

J'ai eu un problème similaire lors du vidage d'une base de données Django mysql avec une seule table. J'ai pu résoudre le problème en vidant la base de données dans un fichier texte, en déplaçant la table en question à la fin du fichier à l'aide d'emacs et en important le fichier de vidage sql modifié dans la nouvelle instance.

HTH Uwe

aspirateur
la source
1

J'ai corrigé le problème en faisant accepter la variable null

ALTER TABLE `ajout_norme` 
CHANGE `type_norme_code` `type_norme_code` VARCHAR( 2 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL
Fahmi
la source
1

J'ai eu le même problème lors de l'exécution d'une série de commandes MySQL. Le mien se produit lors de la création d'une table lors du référencement d'une clé étrangère vers une autre table qui n'a pas encore été créée. C'est la séquence d'existence de la table avant le référencement.

La solution: créez d'abord les tables parentes avant de créer une table enfant qui a une clé étrangère.

ronIT
la source
1

Créez la table sans clé étrangère, puis définissez la clé étrangère séparément.

stuckhelper
la source