mysql La contrainte de clé étrangère est une erreur de forme incorrecte

173

J'ai deux tables, table1est la table parent avec une colonne IDet table2une colonne IDFromTable1(pas le nom réel) quand je mets un FK sur IDFromTable1d' IDen table1je reçois l'erreur Foreign key constraint is incorrectly formed error. Je voudrais supprimer l'enregistrement du tableau 2 si l' table1enregistrement est supprimé. Merci pour toute aide

ALTER TABLE `table2`  
   ADD CONSTRAINT `FK1` 
      FOREIGN KEY (`IDFromTable1`) REFERENCES `table1` (`ID`) 
      ON UPDATE CASCADE 
      ON DELETE CASCADE;

Faites-moi savoir si d'autres informations sont nécessaires. Je suis nouveau sur mysql

user516883
la source
4
Quel moteur utilisez-vous pour vos tables? Quel est le type de table2.IDFromTable1et table1.ID?
Romain
5
Vérifiez également que les jeux de caractères des deux tables sont identiques.
Carsten
Les deux moteurs de tables sont innoDB. Je ne sais pas où trouver les jeux de caractères, et les deux sont de type char. L'ID est la clé primaire dans la table1
user516883
2
Veuillez fournir des définitions de tableau pour le tableau 1 et le tableau 2. Comment avez-vous eu cette erreur? Utilisez-vous un outil pour créer la clé étrangère? Il semble que ce ne soit pas une erreur native MySQL.
Devart
@ user516883 - Avez-vous besoin d'aide pour obtenir des définitions de table? Dans HeidiSQL, vous pouvez simplement cliquer sur l' onglet CRÉER le code .
Álvaro González

Réponses:

422

J'ai rencontré ce même problème avec HeidiSQL. L'erreur que vous recevez est très cryptique. Mon problème a finalement été que la colonne de clé étrangère et la colonne de référence n'étaient pas du même type ou de la même longueur.

La colonne de clé étrangère était SMALLINT(5) UNSIGNEDet la colonne référencée était INT(10) UNSIGNED. Une fois que j'ai fait les deux le même type exact, la création de clé étrangère a parfaitement fonctionné.

Jake Wilson
la source
58
Ou peut-être que la colonne référencée n'est pas une clé primaire
nawfal
9
Un problème similaire pour moi - la table référencée n'existait pas encore. Oups.
Amalgovinus
5
J'ai totalement expérimenté ce que Jake a fait, mais j'ai rencontré un autre problème FK (type différent) sur HeidiSQL. FK sur varchars doit être le même classement. J'espère que cela aidera quelqu'un d'autre à l'avenir!
cbloss793
10
Dans mon cas, c'était à cause d'un encodage et d'un classement différents.
Khatri
1
@nawfal - Je pense que ce ne doit pas nécessairement être une clé primaire, mais il DOIT avoir un index. Les clés primaires sont automatiquement indexées.
Itai
48

J'ai eu le même problème lorsque la table parent a été créée à l'aide du MyISAMmoteur. C'est une erreur stupide, que j'ai corrigée avec:

ALTER TABLE parent_table ENGINE=InnoDB;
Denis Malinovsky
la source
Merci beaucoup, je devenais fou avec ça. Une idée pourquoi la base de données changerait soudainement le moteur des tables?
Robert Franklin
28

assurez-vous que les colonnes sont identiques (du même type) et si la colonne de référence ne l'est pas primary_key, assurez-vous qu'elle l'est INDEXED.

Santosh
la source
Il m'est même arrivé qu'il n'y avait pas d'erreur, mais la clé étrangère n'a pas été ajoutée (1 était et 1 ne l'était pas réellement), mais après avoir ajouté une simple définition KEY referencing_column(referencing_column) AVANT les deux clés étrangères, elles ont été ajoutées avec succès :)
jave.web
2
Les clés non indexées étaient mon problème.
Neil Masters
1
J'ai eu ce problème et le problème était que j'avais une clé primaire à double colonne et que vous ne pouvez pas utiliser la 2ème colonne de la clé primaire comme clé étrangère. Je viens donc d'ajouter mon propre index pour la 2ème colonne de la clé primaire, puis cela a fonctionné.
Firze le
21

La syntaxe pour définir les clés étrangères est très indulgente, mais pour quiconque trébuche là-dessus, le fait que les clés étrangères doivent être "du même type" s'applique même au classement, pas seulement au type de données, à la longueur et à la signature des bits.

Non pas que vous mélangiez le classement dans votre modèle (le feriez-vous?), Mais si vous le faites, assurez-vous que vos champs de clé primaire et étrangère sont du même type de classement dans phpmyadmin ou Heidi SQL ou tout ce que vous utilisez.

J'espère que cela vous évite les quatre heures d'essais et d'erreurs que cela m'a coûté.

utilisateur2297047
la source
1
Merci! Il s'avère que mon hébergeur en ligne utilise le moteur ISAM et pour les développeurs locaux, j'utilise InnoDB. Quand j'ai sauvegardé une table de l'hôte au local ... boom.
Ben
Les versions récentes de MariaDB semblent utiliser utf8_mb4 comme jeu de caractères par défaut (lorsqu'il n'est pas défini explicitement dans la configuration du serveur), de même que COLLATE utf8mb4_unicode_cimon problème (inattendu) (sur la machine de développement).
JonnyJD
13

J'ai eu le même problème, mais je l'ai résolu.

Assurez-vous simplement que la colonne 'ID' dans 'table1' a un index UNIQUE !

Et bien sûr, le type et la longueur des colonnes «ID» et «IDFromTable1» dans ces deux tables doivent être identiques. Mais vous le savez déjà.

Renat Gatin
la source
Tu as fait ma journée.
kevenlolo
1
Heureux de vous aider! ;)
Renat Gatin
Je ne suis pas sûr des détails, mais j'avais une clé composite avec cette erreur qui a été corrigée en ajoutant des index uniques individuels pour les colonnes.
Halvor Holsten Strand
La colonne référencée doit être indexée, elle n'a pas besoin d'être unique (bien que ce soit le cas habituel).
Barmar
10

Juste pour terminer.

Cette erreur peut également être le cas si vous avez une clé étrangère avec VARCHAR (..) et que le jeu de caractères de la table référencée est différent de la table qui la référence.

Par exemple, VARCHAR (50) dans une table Latin1 est différent du VARCHAR (50) dans une table UTF8.

S Doering
la source
1
Même utf8_unicode_ci et utf8_general_ci sont à l'origine de l'erreur
leuchtdiode
10

Les textes d'erreur de mysql n'aident pas tellement, dans mon cas, la colonne avait une contrainte "not null", donc le "on delete set null" n'était pas autorisé

Luca C.
la source
7

si tout va bien, ajoutez simplement ->unsigned();à la fin de foregin key.

si cela ne fonctionne pas, vérifiez le type de données des deux champs. ils doivent être les mêmes.

Josef
la source
5

J'ai eu le même problème, les deux colonnes étaient INT (11) NOT NULL mais je ne serais pas capable de créer la clé étrangère. J'ai dû désactiver les vérifications de clés étrangères pour l'exécuter avec succès:

SET FOREIGN_KEY_CHECKS=OFF;
ALTER TABLE ... ADD CONSTRAINT ...
SET FOREIGN_KEY_CHECKS=ON;

J'espère que cela aide quelqu'un.

Takman
la source
4
En fait c'est FOREIGN_KEY_CHECKS
Xmanoux
Cela m'a aidé à aller plus loin, mais mon problème manquait d'index primaire dans la colonne
bumerang
4

Une autre cause probable pour l'affichage de cette erreur. L'ordre dans lequel je créais les tables était incorrect. J'essayais de référencer une clé d'une table qui n'était pas encore créée.

Toast Kaya
la source
4

(Dernier renvoi) Même si le nom du champ et le type de données sont identiques mais que le classement n'est pas le même, cela entraînera également ce problème.

Par exemple

    NOM TBL | TYPE DE DONNÉES | COLLATION        

    ActivityID | INT |         latin1_general_ci     ActivityID | INT |         utf8_general_ci

Essayez de le changer en

    NOM TBL | TYPE DE DONNÉES | COLLATION        

    ActivityID | INT |         latin1_general_ci     ActivityID | INT |         latin1_general_ci

....

Cela a fonctionné pour moi.

Jimwel Anobong
la source
3

Vérifiez le moteur des tables, les deux tables doivent être le même moteur, cela m'a beaucoup aidé.

mariobigboy
la source
Bon point! J'ai affaire à une base de données Zen Cart dans MySQL dont les tables sont toutes dans le moteur MyISAM par défaut. J'ai ajouté une table à l'aide du moteur InnoDB et j'ai essayé d'ajouter une contrainte de clé étrangère de ma table à celle de base de Zen Cart. Il a échoué avec cette erreur obscure «mal formée». Vous pouvez voir le moteur de chaque table avecSHOW TABLE STATUS LIKE 'table_name';
Neek
2

J'ai eu les mêmes problèmes.

Le problème est que la colonne de référence n'est pas une clé primaire.

Faites-en une clé primaire et le problème est résolu.

Longluffy
la source
Il n'a pas besoin d'être un PK, il peut également être UNIQUE NON NULL.
philipxy
En fait ... dans mon cas, il suffit de le définir sur un type d'index normal fonctionné.
hendr1x
2

Bien que les autres réponses soient très utiles, je voulais simplement partager mon expérience également.

J'ai rencontré le problème lorsque j'ai supprimé une table dont la idréférence était déjà en tant que clé étrangère dans d'autres tables ( avec des données ) et essayé de recréer / importer la table avec des colonnes supplémentaires.

La requête de récréation (générée dans phpMyAdmin) ressemblait à ceci:

CREATE TABLE `the_table` (
  `id` int(11) NOT NULL,            /* No PRIMARY KEY index */  
  `name` varchar(255) NOT NULL,
  `name_fa` varchar(255) NOT NULL,
  `name_pa` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

... /* SOME DATA DUMP OPERATION */

ALTER TABLE `the_table`
  ADD PRIMARY KEY (`id`), /* PRIMARY KEY INDEX */
  ADD UNIQUE KEY `uk_acu_donor_name` (`name`);

Comme vous pouvez le remarquer, l' PRIMARY KEYindex a été défini après la création ( et l'insertion des données ) qui causait le problème.

Solution

La solution consistait à ajouter l' PRIMARY KEYindex sur la requête de définition de table pour le idqui était référencé en tant que clé étrangère, tout en le supprimant également de la ALTER TABLEpartie où les index étaient définis:

CREATE TABLE `the_table` (
  `id` int(11) NOT NULL PRIMARY KEY,            /* <<== PRIMARY KEY INDEX ON CREATION */  
  `name` varchar(255) NOT NULL,
  `name_fa` varchar(255) NOT NULL,
  `name_pa` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Ahmad Baktash Hayeri
la source
Cela a fonctionné pour moi. J'avais peur de devoir réinstaller mon logiciel;)
Dewlance
2

J'ai perdu des heures pour ça!

PK dans une table était utf8dans l'autre était utf8_unicode_ci!

LukaszTaraszka
la source
1

Essayez d'exécuter ce qui suit:

show create table Parent

// et vérifiez si le type des deux tables est le même, comme myISAM ou innoDB, etc.
// Autres aspects à vérifier avec ce message d'erreur: les colonnes utilisées comme étrangères 
les clés doivent être indexées, elles doivent être du même type 
(si ie l'un est de type smallint (5) et l'autre de type smallint (6), 
cela ne fonctionnera pas) et, si ce sont des entiers, ils devraient être non signés.

// ou vérifier les jeux de caractères
afficher des variables comme "character_set_database";
afficher des variables comme "collation_database";

// modifié: essayez quelque chose comme ça
ALTER TABLE table2
AJOUTER CONSTRAINT fk_IdTable2
CLÉ ÉTRANGÈRE (Table1_Id)
RÉFÉRENCES Table1 (Table1_Id)
SUR LA MISE À JOUR DE LA CASCADE 
SUR SUPPRIMER LA CASCADE;
Sudhir Bastakoti
la source
9
Essayez d'exécuter SHOW ENGINE INNODB STATUS pour obtenir plus de détails sur l'erreur
Sudhir Bastakoti
@SudhirBastakoti - +1! Cela l'a fait pour moi. Les détails sont utiles. A pu résoudre le problème rapidement.
Paul Carlton
1

J'ai eu le même problème avec Symfony 2.8.

Je ne l'ai pas compris au début, car il n'y avait pas de problèmes similaires avec la longueur int des clés étrangères, etc.

Enfin, j'ai dû faire ce qui suit dans le dossier du projet. (Un redémarrage du serveur n'a pas aidé!)

app/console doctrine:cache:clear-metadata app/console doctrine:cache:clear-query app/console doctrine:cache:clear-result

rogaa
la source
1

merci S Doerin:

"Juste pour terminer. Cette erreur peut également être le cas si vous avez une clé étrangère avec VARCHAR (..) et que le jeu de caractères de la table référencée est différent de la table qui la référence. Par exemple, VARCHAR (50) dans une table Latin1 est différent du VARCHAR (50) dans une table UTF8. "

J'ai résolu ce problème, en changeant le type de caractères de la table. la création a latin1 et le correct est utf8.

ajoutez la ligne suivante. JEU DE CARACTÈRES PAR DÉFAUT = utf8;

Bladimir Arias Sabogal
la source
1

J'ai eu des problèmes avec Alter table pour ajouter une clé étrangère entre deux tables et la chose qui m'a aidé était de m'assurer que chaque colonne à laquelle j'essayais d'ajouter une relation de clé étrangère était indexée. Pour ce faire en PHP myAdmin: Allez dans le tableau et cliquez sur l'onglet structure. Cliquez sur l'option d'indexation pour indexer la colonne souhaitée comme indiqué dans la capture d'écran:

entrez la description de l'image ici

Une fois que j'ai indexé les deux colonnes que j'essayais de référencer avec mes clés étrangères, j'ai pu utiliser avec succès la table alter et créer la relation de clé étrangère. Vous verrez que les colonnes sont indexées comme dans la capture d'écran ci-dessous:

entrez la description de l'image ici

remarquez comment zip_code apparaît dans les deux tables.

Chris Adams
la source
1

Vous devez vérifier que les deux sont identiques dans toutes ses propriétés, y compris dans "Collation"

CrsCaballero
la source
1

J'utilisais HeidiSQL et pour résoudre ce problème, j'ai dû créer un index dans la table référencée avec toutes les colonnes référencées.

ajout d'un index à la table Heidisql

Doug
la source
Pareil pour moi dans mysql: InnoDB nécessite des index sur des clés étrangères et des clés référencées afin que les vérifications de clés étrangères puissent être rapides et ne nécessitent pas de scan de table.
hendr1x
1

Je suis tombé sur le même problème tout à l'heure. Dans mon cas, tout ce que j'avais à faire est de m'assurer que la table à laquelle je fais référence dans la clé étrangère doit être créée avant la table actuelle (plus tôt dans le code). Donc, si vous faites référence à une variable (x * 5), le système doit savoir ce qu'est x (x doit être déclaré dans les premières lignes de code). Cela a résolu mon problème, j'espère que cela aidera quelqu'un d'autre.

Alexandre Nenartovich
la source
J'ai eu le même problème dans MariaDB v10.3.18. Nous avons utilisé MySQL avant et il a averti qu'une clé étrangère pointait vers une table inexistante.
MarthyM
0

J'ai eu le même problème avec Laravel 5.1 migration Schema Builder avec MariaDB 10.1.

Le problème était que j'avais tapé unignedau lieu de unsigned(la slettre manquait) lors de la définition de la colonne.

Après avoir corrigé l'erreur de frappe a été corrigée pour moi.

Arda
la source
0

Même moi, j'ai rencontré le même problème avec mysql et liquibase. Voici donc le problème: la table à partir de laquelle vous souhaitez référencer une colonne d'une autre table est différente soit en cas de type de données, soit en termes de taille du type de données.

Error appears in below scenario:
Scenario 1:
Table A has column id, type=bigint
Table B column referenced_id type varchar(this column gets the value from the id column of Table A.)
Liquibase changeset for table B:

    <changeset id="XXXXXXXXXXX-1" author="xyz">
            <column name="referenced_id" **type="varchar"**>
        </column>
            </changeset>
    <changeSet id="XXXXXXXXXXX-2" author="xyz">
                <addForeignKeyConstraint constraintName="FK_table_A"
                    referencedTableName="A" **baseColumnNames="referenced_id**"
                    referencedColumnNames="id" baseTableName="B" />
    </changeSet>

Table A changeSet:

    <changeSet id="YYYYYYYYYY" author="xyz">
     <column **name="id"** **type="bigint"** autoIncrement="${autoIncrement}">
                    <constraints primaryKey="true" nullable="false"/>
                </column>
    </changeSet>

Solution: 
correct the type of table B to bigint because the referenced table has type bigint.

Scenrario 2:
The type might be correct but the size might not.
e.g. :
Table B : referenced column type="varchar 50"
Table A : base column type ="varchar 255"

Solution change the size of referenced column to that of base table's column size.
Ashish Kathait
la source
0

Vérifiez que vous avez spécifié le nom de la table dans la casse appropriée (si les noms de table sont sensibles à la casse dans votre base de données). Dans mon cas, j'ai dû changer

 CONSTRAINT `FK_PURCHASE_customer_id` FOREIGN KEY (`customer_id`) REFERENCES `customer` (`id`) ON UPDATE CASCADE ON DELETE CASCADE

à

 CONSTRAINT `FK_PURCHASE_customer_id` FOREIGN KEY (`customer_id`) REFERENCES `CUSTOMER` (`id`) ON UPDATE CASCADE ON DELETE CASCADE

notez le customerchangement en CUSTOMER.

izogfif
la source
0

Ou vous pouvez utiliser DBDesigner4 qui a une interface graphique pour créer votre base de données et les relier à l'aide de FK. Faites un clic droit sur votre table et sélectionnez «Copier la table SQL Create» qui crée le code.

entrez la description de l'image ici

Dexter
la source
0

C'est un vieux sujet mais j'ai découvert quelque chose. Lors de la construction d'un plan de travail MySQL, il obtient également les relations de l'autre table. laissez simplement les piliers auxquels vous vous rapportez. Effacez les autres colonnes ajoutées automatiquement. Cela fonctionne pour moi.

Muhammed Alper Uslu
la source
0

Mon cas était que j'avais une faute de frappe sur la colonne référencée:

MariaDB [blog]> alter table t_user add FOREIGN KEY ( country_code ) REFERENCES t_country ( coutry_code );
ERROR 1005 (HY000): Can't create table `blog`.`t_user` (errno: 150 "Foreign key constraint is incorrectly formed")

Le message d'erreur est assez cryptique et j'ai tout essayé - vérifier les types de colonnes, les classements, les moteurs, etc.

Il m'a fallu un certain temps pour noter la faute de frappe et après avoir corrigé tout a bien fonctionné:

MariaDB [blog]> alter table t_user add FOREIGN KEY ( country_code ) REFERENCES t_country ( country_code );
Query OK, 2 rows affected (0.039 sec)              
Records: 2  Duplicates: 0  Warnings: 0
Delian Krustev
la source
0

Je fais face à ce problème, l'erreur est survenue lorsque vous mettez la clé primaire dans un type de données différent comme:

Tableau 1:

 Schema::create('products', function (Blueprint $table) {
            $table->increments('id');
            $table->string('product_name');
        });

Tableau 2:

Schema::create('brands', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('brand_name');
        });

le type de données pour l'id de la deuxième table doit être des incréments

shaher11
la source
0

Le problème est très simple à résoudre

par exemple: vous avez deux tables avec des noms d' utilisateurs et de publications et vous voulez créer une clé étrangère dans la table des publications et vous utilisez phpMyAdmin

1) dans la table de publication , ajoutez une nouvelle colonne ( nom : use_id | type : comme l' id dans la table des utilisateurs | Longueur : comme l' id dans la table des utilisateurs | Par défaut : NULL | Attributs : unsigned | index: INDEX)

2) sur l' onglet Structure, allez à la vue relation ( Nom de la contrainte : défini automatiquement par phpmyAdmin | nom de la colonne : sélectionnez id_utilisateur | table : utilisateurs | clé : id, ...)

C'était simplement résolu

javad mosavi iran / urmie

Javad Mosavi
la source