MySQL no puede crear una restricción de clave externa

84

Tengo algunos problemas para crear una clave externa para una tabla existente en una base de datos mysql.

Tengo la mesa 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    |       |
+-------------+------------------+------+-----+---------+-------+

y no quiero crear una nueva tabla llamada sample_dfreferenciando esto, usando lo siguiente:

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)
);

Pero me sale el error:

ERROR 1215 (HY000): Cannot add foreign key constraint

Para obtener más información lo hice:

SHOW ENGINE INNODB STATUS\G

De lo que obtuve:

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.

Para mí, los tipos de columna parecen coincidir, ya que ambos son varchar (45). (También intenté configurar la experimentcolumna como no nula, pero esto no lo solucionó) Así que supongo que el problema debe ser ese Cannot find an index in the referenced table where the referenced columns appear as the first columns. Pero no estoy muy seguro de lo que esto significa, o cómo verificarlo / solucionarlo. ¿Alguien tiene alguna sugerencia? ¿Y qué se entiende por first columns?

numfar
fuente
11
En ninguna parte de la respuesta o pregunta, pude encontrar que este error puede ocurrir debido a la diferencia en el conjunto de caracteres. Gracias .. Saludos !!!
proprius
3
Además, verifique dos veces la clasificación de sus columnas. Su tabla podría ser utf8mb4 pero la columna puede tener una colación diferente.
Watson
@Watson charset en mi caso, pero recibes mi voto a favor por hacerme pensar.
user2910265

Respuestas:

153

Simplemente agregando esto a la combinación de posibles causas, me encontré con esto cuando la columna de la tabla de referencia tenía el mismo "tipo" pero no tenía la misma firma.

En mi caso, la columna de la tabla de referencia era TINYINT SIN FIRMAR y la columna de mi tabla de referencia era TINYINT FIRMADA. Alinear ambas columnas resolvió el problema.

Austen Hoogen
fuente
1
La solución sugerida por @ austen-hoogen ha resuelto mi problema. Pero debido a los bajos puntajes de reputación, no puedo votar ni comentar su solución. En mi caso, la clave principal era entera, de incremento automático y sin firmar. Pero la clave externa (columna de la tabla de referencia) fue de tipo firmado. Lo cambié a unsigned y pude crear una relación con éxito.
Bal Singh
Sí, pasó por el mismo problema. Mi clave principal era BIGINT (20), y mi clave referenciada en otra tabla era INT (10) sin firmar. Necesitamos asegurarnos de que todos coincidan. es decir. BIGINT (20), y en la tabla de referencia también debe ser BIGINT (20)
Manjunath Reddy
¡Gracias! ¡Esta solución también resolvió mi problema! Tenía inten la tabla donde estaba planeando establecer la clave externa y el bigint en la segunda tabla.
Aleksej_Shherbak
36

Este error también puede ocurrir si la tabla de referencias y la tabla actual no tienen el mismo juego de caracteres.

Pratik Singhal
fuente
3
Después de configurar el conjunto de caracteres como latinen la tabla de referencia, comencé a respirar nuevamente después de 3 horas.
Abhishek Kamal
24

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

MySQL requiere índices en claves externas y claves referenciadas para que las comprobaciones de claves externas puedan ser rápidas y no requieran un escaneo de tabla. En la tabla de referencia, debe haber un índice donde las columnas de clave externa se enumeran como las primeras columnas en el mismo orden.

InnoDB permite que una clave externa haga referencia a cualquier columna de índice o grupo de columnas. Sin embargo, en la tabla a la que se hace referencia, debe haber un índice donde las columnas a las que se hace referencia se enumeran como las primeras columnas en el mismo orden.

Entonces, si el índice en la tabla referenciada existe y consta de varias columnas, y la columna deseada no es la primera, se producirá el error.

La causa de nuestro error se debió a la violación de la siguiente regla:

Las columnas correspondientes en la clave externa y la clave referenciada deben tener tipos de datos similares. El tamaño y el signo de los tipos enteros deben ser iguales. La longitud de los tipos de cadenas no tiene por qué ser la misma. Para columnas de cadenas no binarias (de caracteres), el conjunto de caracteres y la intercalación deben ser iguales.

Anton
fuente
19

Como mencionó @Anton, esto podría deberse a los diferentes tipos de datos. En mi caso, tenía la clave principal BIGINT (20) y traté de configurar la clave delantera con INT (10)

antongorodezkiy
fuente
2
¡Gracias! Problema similar en el que estaba usando INT (11) con INT (11) pero una era una clave principal y, por lo tanto, sin firmar mientras que la otra estaba firmada.
Michael Scott Cuthbert
@MichaelScottCuthbert Same
Germa Vinsmoke
6

El mío fue un problema de clasificación entre la tabla a la que se hace referencia y la tabla que se va a crear, por lo que tuve que establecer explícitamente el tipo de clasificación de la clave a la que hacía referencia.

  • Primero ejecuté una consulta en la tabla referenciada para obtener su tipo de intercalación
show table STATUS like '<table_name_here>';
  • Luego copié el tipo de intercalación e indiqué explícitamente el tipo de intercalación de employee_id en la consulta de creación. En mi caso fue utf8_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)
);
usuario11891461
fuente
2

El orden exacto de la clave principal también debe coincidir sin columnas adicionales en el medio.

Tenía una configuración de clave principal en la que el orden de las columnas realmente coincide, pero el problema era que la clave principal tenía una columna adicional que no forma parte de la clave externa de la tabla de referencia

p. ej.) tabla 2, columna (a, b, c) -> tabla 1, columna (a, b, d, c) - ESTO FALLA

Tuve que reordenar las columnas de clave principal para que no solo estén ordenadas de la misma manera, sino que no tengan columnas adicionales en el medio:

Ej.) tabla 2, columna (a, b, c) -> tabla 1, columna (a, b, c, d) - ESTO TIENE ÉXITO

Nelson
fuente
2

En algunos casos, tuve que hacer que el campo referenciado fuera único además de definirlo como la clave principal.

Pero descubrí que no definirlo como único no crea un problema en todos los casos. Sin embargo, no he podido descifrar los escenarios. Probablemente algo que ver con la definición que acepta valores NULL.

Sprksh
fuente
¿Ha leído una introducción a los FK o el manual? Un FK hace referencia a un ÚNICO; PK significa ÚNICO NO NULO.
philipxy
2

En mi caso, se creó usando integer para la identificación, y la tabla de referencia estaba creando de forma predeterminada una clave externa usando bigint .

Esto causó una gran pesadilla en mi aplicación Rails ya que la migración falló, pero los campos se crearon en realidad en la base de datos, por lo que aparecieron en la base de datos pero no en el esquema de la aplicación Rails.

helenatxu
fuente
1

Hacer referencia a la misma columna más de una vez en la misma restricción también produce este Cannot find an index in the referenced tableerror, pero puede ser difícil de detectar en tablas grandes. Divida las restricciones y funcionará como se esperaba.

Eduardo
fuente
1

También tuve este error. Ninguna de las respuestas me pertenecía. En mi caso, mi GUI crea automáticamente una tabla con un identificador único principal como "no asignado". Esto falla cuando intento crear una clave externa y me da exactamente el mismo error. Es necesario asignar mi clave principal.

Si escribe el SQL en sí mismo así, id int unique auto_incremententonces no tiene este problema, pero por alguna razón mi GUI lo hace en su lugar id int unassigned unique auto_increment.

Espero que esto ayude a alguien más en el futuro.

Paul Carlton
fuente
1

Para mí fue solo el juego de caracteres y la colación de la base de datos. Cambié a utf8_unicode_ci y funciona

Diego Herrera
fuente
1
¿Podría incluir un ejemplo de cómo verificar el juego de caracteres / colación actual?
thelr