web-dev-qa-db-fra.com

MySQL ne peut pas créer de contrainte de clé étrangère

J'ai des problèmes pour créer une clé étrangère vers une table existante dans une base de données mysql.

J'ai la table exp:

+-------------+------------------+------+-----+---------+-------+
| Field       | Type             | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+-------+
| EID         | varchar(45)      | NO   | PRI | NULL    |       |
| Comment     | text             | YES  |     | NULL    |       |
| Initials    | varchar(255)     | NO   |     | NULL    |       |
| ExpDate     | date             | NO   |     | NULL    |       |
| InsertDate  | date             | NO   |     | NULL    |       |
| inserted_by | int(11) unsigned | YES  | MUL | NULL    |       |
+-------------+------------------+------+-----+---------+-------+

et je ne veux pas créer une nouvelle table appelée sample_df en référençant ceci, en utilisant ce qui suit:

CREATE TABLE sample_df (
df_id mediumint(5) unsigned AUTO_INCREMENT primary key,
sample_type mediumint(5) unsigned NOT NULL,
df_10 BOOLEAN NOT NULL,
df_100 BOOLEAN NOT NULL,
df_1000 BOOLEAN NOT NULL,
df_above_1000 BOOLEAN NOT NULL,
target INT(11) unsigned NOT NULL,
assay MEDIUMINT(5) unsigned zerofill NOT NULL,
insert_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
inserted_by INT(11) unsigned NOT NULL,
initials varchar(255),
experiment VARCHAR(45),
CONSTRAINT FOREIGN KEY (inserted_by) REFERENCES user (iduser),
CONSTRAINT FOREIGN KEY (target) REFERENCES protein (PID),
CONSTRAINT FOREIGN KEY (sample_type) REFERENCES sample_type (ID),
CONSTRAINT FOREIGN KEY (assay) REFERENCES assays (AID),
CONSTRAINT FOREIGN KEY (experiment) REFERENCES exp (EID)
);

Mais je reçois l'erreur:

ERROR 1215 (HY000): Cannot add foreign key constraint

Pour obtenir plus d'informations, j'ai fait:

SHOW ENGINE INNODB STATUS\G

D’où j’ai obtenu:

FOREIGN KEY (experiment) REFERENCES exp (EID)
):
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.

Pour moi, les types de colonnes semblent correspondre, car ils sont tous les deux varchar (45). (J'ai également essayé de définir la colonne experiment sur non null, mais cela ne l'a pas corrigé) Donc, je suppose que le problème doit être cette Cannot find an index in the referenced table where the referenced columns appear as the first columns. Mais je ne sais pas trop ce que cela signifie, ni comment le vérifier/corriger. Est-ce que quelqu'un a des suggestions? Et que signifie first columns?

52
numfar

Juste en jetant cela dans le mélange des causes possibles, je suis tombé sur cela lorsque la colonne de la table de référence avait le même "type" mais n'avait pas la même signature.

Dans mon cas, la colonne de table référencée était TINYINT UNSIGNED et ma colonne de table de référence était TINYINT SIGNED. L'alignement des deux colonnes a résolu le problème.

96
Austen Hoogen

Selon http://dev.mysql.com/doc/refman/5.5/en/create-table-foreign-keys.html

MySQL nécessite des index sur les clés étrangères et les clés référencées afin que les vérifications de clés étrangères puissent être rapides et ne nécessitent pas une analyse de table. Dans la table de référence, il doit y avoir un index dans lequel les colonnes de clé étrangère sont répertoriées en tant que premières colonnes dans le même ordre.

InnoDB permet à une clé étrangère de référencer n'importe quelle colonne d'index ou groupe de colonnes. Cependant, dans la table référencée, il doit y avoir un index dans lequel les colonnes référencées sont répertoriées en tant que premières colonnes dans le même ordre.

Donc, si l'index dans la table référencée existe et qu'il est composé de plusieurs colonnes et que la colonne souhaitée n'est pas la première, l'erreur doit se produire.

La cause de notre erreur était due à la violation de la règle suivante:

Les colonnes correspondantes dans la clé étrangère et la clé référencée doivent avoir des types de données similaires. La taille et le signe des types entiers doivent être identiques. La longueur des types de chaînes n'a pas besoin d'être la même. Pour les colonnes de chaînes non binaires (caractères), le jeu de caractères et le classement doivent être identiques.

19
Anton

Cette erreur peut également se produire si la table de références et la table actuelle n'ont pas le même jeu de caractères.

10
Pratik Singhal

Comme mentionné @Anton, cela pourrait être dû au type de données différent. Dans mon cas, j'avais la clé primaire BIGINT (20) et j'ai essayé de définir la clé de premier plan avec INT (10)

10
antongorodezkiy

Dans mon cas, il s'est avéré que la colonne référencée n'a pas été déclarée principale ou unique.

https://stackoverflow.com/a/18435114/1763217

5
Nick Manning

L'ordre exact de la clé primaire doit également correspondre sans colonne supplémentaire entre les deux.

J'avais une configuration de clé primaire où l'ordre des colonnes correspond réellement, mais le problème était que la clé primaire avait une colonne supplémentaire qui ne faisait pas partie de la clé étrangère de la table de référencement

par exemple) tableau 2, colonne (a, b, c) -> tableau 1, colonne (a, b, d, c) - CECI ÉCHOUE

J'ai dû réorganiser les colonnes de clé primaire afin que non seulement elles soient ordonnées de la même manière, mais qu'elles n'aient pas de colonnes supplémentaires au milieu:

par exemple) tableau 2, colonne (a, b, c) -> tableau 1, colonne (a, b, c, d) - CE SUCCÈS

1
Nelson

Le mien était un problème de classement entre la table référencée et la table à créer, j'ai donc dû définir explicitement le type de classement de la clé à laquelle je faisais référence.

  • J'ai d'abord exécuté une requête sur la table référencée pour obtenir son type de classement
show table STATUS like '<table_name_here>';
  • J'ai ensuite copié le type de classement et indiqué explicitement le type de classement de employee_id lors de la requête de création. Dans mon cas, c'était tf8_general_ci
CREATE TABLE dbo.sample_db
(
  id INT PRIMARY KEY AUTO_INCREMENT,
  event_id INT SIGNED NOT NULL,
  employee_id varchar(45) COLLATE utf8_general_ci NOT NULL,
  event_date_time DATETIME,
  CONSTRAINT sample_db_event_event_id_fk FOREIGN KEY (event_id) REFERENCES event (event_id),
  CONSTRAINT sample_db_employee_employee_id_fk FOREIGN KEY (employee_id) REFERENCES employee (employee_id)
);
0
user11891461

Dans certains cas, j'ai dû rendre le champ référencé unique en plus de le définir comme clé primaire.

Mais j'ai trouvé que ne pas le définir comme unique ne crée pas de problème dans tous les cas. Je n'ai cependant pas été en mesure de comprendre les scénarios. Probablement quelque chose à voir avec la définition nullable.

0
sprksh

J'ai aussi eu cette erreur. Aucune des réponses ne me concernait. Dans mon cas, mon interface graphique crée automatiquement une table avec un identifiant unique principal comme "non attribué". Cela échoue lorsque j'essaie de créer une clé étrangère et me donne exactement la même erreur. Ma clé primaire doit être attribuée.

Si vous écrivez le SQL lui-même comme ceci id int unique auto_increment alors vous n'avez pas ce problème mais pour une raison quelconque mon interface graphique le fait à la place id int unassigned unique auto_increment.

J'espère que cela aide quelqu'un d'autre sur la route.

0
Paul Carlton

Le fait de référencer la même colonne plusieurs fois dans la même contrainte produit également ce Cannot find an index in the referenced table erreur, mais peut être difficile à repérer sur les grandes tables. Répartissez les contraintes et cela fonctionnera comme prévu.

0
Edward