mysql La restricción de clave externa es un error formado incorrectamente

173

Tengo dos tablas, table1es la tabla primaria con una columna IDy table2con una columna IDFromTable1(no el nombre real) cuando pongo un FK en IDFromTable1que IDen table1que sale el error Foreign key constraint is incorrectly formed error. Me gustaría eliminar el registro de la tabla 2 si el table1registro se elimina. Gracias por cualquier ayuda

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

Avíseme si necesita otra información. Soy nuevo en mysql

usuario516883
fuente
44
¿Qué motor estás usando para tus mesas? ¿Cuál es el tipo de table2.IDFromTable1y table1.ID?
Romain
55
Además, verifique que los conjuntos de caracteres para ambas tablas sean iguales.
Carsten
Los motores de ambas tablas son innoDB. no estoy seguro de dónde encontrar conjuntos de caracteres, y ambos son de tipo char. El ID es la clave principal en la
tabla1
2
Proporcione definiciones de tabla para tabla1 y tabla2. ¿Cómo conseguiste este error? ¿Utiliza una herramienta para crear la clave externa? Parece que no es un error nativo de MySQL.
Devartir el
@ user516883 - ¿Necesita ayuda para obtener definiciones de tabla? En HeidiSQL, simplemente puede hacer clic en la pestaña CREAR código .
Álvaro González

Respuestas:

422

Me encontré con este mismo problema con HeidiSQL. El error que recibe es muy críptico. Mi problema terminó siendo que la columna de clave externa y la columna de referencia no eran del mismo tipo o longitud.

La columna de clave externa era SMALLINT(5) UNSIGNEDy la columna referenciada era INT(10) UNSIGNED. Una vez que los hice del mismo tipo exacto, la creación de clave externa funcionó perfectamente.

Jake Wilson
fuente
58
O puede ser que la columna se hace referencia no es una clave principal
nawfal
9
Un problema similar para mí: la tabla referenciada aún no existía. Whoops
Amalgovinus
55
He experimentado totalmente lo que hizo Jake, pero me he encontrado con otro problema de FK (tipo diferente) en HeidiSQL. FK en varchars debe ser la misma colación. ¡Espero que ayude a alguien más en el futuro!
cbloss793
10
En mi caso fue por diferentes codificaciones y colaciones.
Khatri
1
@nawfal: creo que no necesariamente tiene que ser una clave principal, pero DEBE tener un índice. Las claves primarias se indexan automáticamente.
Itai
48

Tuve el mismo problema cuando la tabla principal se creó usando el MyISAMmotor. Es un error tonto, que solucioné con:

ALTER TABLE parent_table ENGINE=InnoDB;
Denis Malinovsky
fuente
Muchas gracias, me estaba volviendo loco con esto. ¿Alguna idea de por qué la base de datos de repente cambiaría el motor por tablas?
Robert Franklin
28

asegúrese de que las columnas sean idénticas (del mismo tipo) y si la columna de referencia no lo es primary_key, asegúrese de que lo sea INDEXED.

Santosh
fuente
Incluso me ocurrió que no hubo ningún error, pero no se agregó la clave externa (1 fue y 1 no fue realmente), pero después de agregar simple KEY referencing_column(referencing_column) ANTES de que ambas definiciones de clave externa se agregaran con éxito :)
jave.web
2
Las claves que no se indexan eran mi problema.
Neil Masters el
1
Tuve este problema y el problema era que tenía una clave principal de doble columna y no puede usar la segunda columna de la clave primaria como clave externa. Así que acabo de agregar un índice propio para la segunda columna de la clave primaria y luego funcionó.
Firze
21

La sintaxis para definir claves foráneas es muy indulgente, pero para cualquiera que esté tropezando con esto, el hecho de que las claves foráneas deben ser "del mismo tipo" se aplica incluso a la clasificación, no solo al tipo de datos y la longitud y la firma de bits.

No es que mezclaría la intercalación en su modelo (¿verdad?), Pero si lo hace, asegúrese de que sus campos de clave primaria y externa sean del mismo tipo de intercalación en phpmyadmin o Heidi SQL o lo que sea que use.

Espero que esto le ahorre las cuatro horas de prueba y error que me costó.

usuario2297047
fuente
1
¡Gracias! Resulta que mi host en línea usa el motor ISAM y para desarrolladores locales uso InnoDB. Cuando hice una copia de seguridad de una mesa del anfitrión al local ... boom.
Ben
Las versiones recientes de MariaDB parecen usar utf8_mb4 como el juego de caracteres predeterminado (cuando no se establece explícitamente en la configuración del servidor), así COLLATE utf8mb4_unicode_cifue mi problema (inesperado) (en la máquina de desarrollo).
JonnyJD
13

Tuve el mismo problema, pero lo resolví.

¡Solo asegúrese de que la columna 'ID' en 'table1' tenga un índice ÚNICO !

Y, por supuesto, el tipo, la longitud de las columnas 'ID' e 'IDFromTable1' en estas dos tablas tiene que ser el mismo. Pero ya sabes sobre esto.

Renat Gatin
fuente
Me has alegrado el día.
kevenlolo
1
¡Encantado de ayudar! ;)
Renat Gatin
No estoy seguro de los detalles, pero tenía una clave compuesta con este error que se solucionó agregando índices únicos individuales para las columnas.
Halvor Holsten Strand
La columna a la que se hace referencia debe indexarse, no tiene que ser única (aunque ese es el caso habitual).
Barmar
10

Solo para completar.

Este error también podría ser el caso si tiene una clave foránea con VARCHAR (..) y el juego de caracteres de la tabla referenciada es diferente de la tabla que hace referencia a ella.

por ejemplo, VARCHAR (50) en una tabla Latin1 es diferente de VARCHAR (50) en una tabla UTF8.

S Doering
fuente
1
Incluso utf8_unicode_ci y utf8_general_ci están causando el error
leuchtdiode
10

los textos de error de mysql no ayudan mucho, en mi caso, la columna tenía una restricción "no nula", por lo que no estaba permitido "on delete set null"

Luca C.
fuente
7

si todo está bien, solo agregue ->unsigned();al final de foregin key.

Si no funciona, verifique el tipo de datos de ambos campos. deben ser lo mismo.

josef
fuente
5

Tuve el mismo problema, ambas columnas eran INT (11) NO NULL pero no podía crear la clave foránea. Tuve que deshabilitar las comprobaciones de claves externas para ejecutarlo con éxito:

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

Espero que esto ayude a alguien.

Takman
fuente
44
En realidad es FOREIGN_KEY_CHECKS
Xmanoux
Esto me ayudó a pasar más lejos, pero mi problema era la falta de índice primario en la columna
bumerang
4

Una causa más probable para la visualización de este error. El orden en el que estaba creando las tablas era incorrecto. Intenté hacer referencia a una clave de una tabla que aún no se había creado.

Tostada Kaya
fuente
4

(Último reenvío) Incluso si el nombre del campo y el tipo de datos son los mismos pero la intercalación no es la misma, también dará lugar a ese problema.

Por ejemplo

    TBL NAME | TIPO DE DATOS | COLACIÓN        

    ActivityID | INT |         latin1_general_ci     ActivityID | INT |         utf8_general_ci

Intenta cambiarlo a

    TBL NAME | TIPO DE DATOS | COLACIÓN        

    ActivityID | INT |         latin1_general_ci     ActivityID | INT |         latin1_general_ci

....

Esto funcionó para mí.

Jimwel Anobong
fuente
3

Verifique el motor de tablas, ambas tablas tienen que ser el mismo motor, eso me ayudó mucho.

mariobigboy
fuente
¡Buen punto! Estoy tratando con una base de datos Zen Cart en MySQL cuyas tablas están todas en el motor MyISAM por defecto. Agregué una tabla usando el motor InnoDB e intenté agregar una restricción de clave externa de mi tabla al núcleo de Zen Cart. Falló con este oscuro error 'incorrectamente formado'. Puedes ver el motor de cada mesa conSHOW TABLE STATUS LIKE 'table_name';
Neek
2

Tenía los mismos problemas.

El problema es que la columna de referencia no es una clave principal.

Conviértalo en una clave principal y el problema está resuelto.

longluffy
fuente
No necesita ser un PK, también puede ser ÚNICO, NO NULO.
philipxy
En realidad ... en mi caso, simplemente configurándolo en un tipo de índice normal funcionó.
hendr1x
2

Aunque las otras respuestas son bastante útiles, solo quería compartir mi experiencia también.

Me enfrenté al problema cuando eliminé una tabla a la que idya se hacía referencia como clave externa en otras tablas ( con datos ) e intenté recrear / importar la tabla con algunas columnas adicionales.

La consulta de recreación (generada en phpMyAdmin) tenía el siguiente aspecto:

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

Como puede observar, el PRIMARY KEYíndice se estableció después de la creación ( e inserción de datos ) que estaba causando el problema.

Solución

La solución fue agregar el PRIMARY KEYíndice en la consulta de definición de tabla para la idque se hacía referencia como clave foránea, y también eliminarlo de la ALTER TABLEparte donde se establecían los índices:

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
fuente
Me ha funcionado. Estaba preocupado de tener que reinstalar mi software;)
Dewlance
2

¡Perdí por horas por eso!

PK en una mesa estaba utf8en otra era utf8_unicode_ci!

LukaszTaraszka
fuente
1

Intenta ejecutar lo siguiente:

mostrar crear tabla principal

// y verifique si el tipo para ambas tablas es el mismo, como myISAM o innoDB, etc.
// Otros aspectos a comprobar con este mensaje de error: las columnas utilizadas como foráneas 
las claves deben estar indexadas, deben ser del mismo tipo 
(si, por ejemplo, uno es del tipo smallint (5) y el otro del tipo smallint (6), 
no funcionará), y, si son enteros, no deben estar firmados.

// o busca charsets
muestra variables como "character_set_database";
mostrar variables como "collation_database";

// editado: prueba algo como esto
ALTER TABLE table2
AGREGAR RESTRICCIÓN fk_IdTable2
CLAVE EXTRANJERA (Table1_Id)
REFERENCIAS Table1 (Table1_Id)
EN ACTUALIZACIÓN EN CASCADA 
EN ELIMINAR CASCADA;
Sudhir Bastakoti
fuente
9
Intente ejecutar SHOW ENGINE INNODB STATUS para obtener más detalles sobre el error
Sudhir Bastakoti
@SudhirBastakoti - +1! Eso lo hizo por mí. Los detalles son útiles. Pude solucionar el problema rápidamente.
Paul Carlton
1

Tuve el mismo problema con Symfony 2.8.

Al principio no lo entendí, porque no había problemas similares con la longitud int de las claves externas, etc.

Finalmente tuve que hacer lo siguiente en la carpeta del proyecto. (¡Un reinicio del servidor no ayudó!)

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

rogaa
fuente
1

gracias S Doerin:

"Solo para completar. Este error también podría ser el caso si tiene una clave externa con VARCHAR (..) y el conjunto de caracteres de la tabla referenciada es diferente de la tabla que hace referencia a ella. Por ejemplo, VARCHAR (50) en una tabla Latin1 es diferente al VARCHAR (50) en una tabla UTF8 ".

Resolví este problema, cambiando el tipo de caracteres de la tabla. la creación tiene latin1 y la correcta es utf8.

agregue la siguiente línea. CONJUNTO DE CARACTERES POR DEFECTO = utf8;

Bladimir Arias Sabogal
fuente
1

Tuve problemas al usar Alter table para agregar una clave externa entre dos tablas y lo que me ayudó fue asegurarme de que cada columna a la que intentaba agregar una relación de clave externa estuviera indexada. Para hacer esto en PHP myAdmin: Vaya a la tabla y haga clic en la pestaña de estructura. Haga clic en la opción de índice para indexar la columna deseada como se muestra en la captura de pantalla:

ingrese la descripción de la imagen aquí

Una vez que indicé ambas columnas que estaba tratando de hacer referencia con mis claves foráneas, pude usar con éxito la tabla alter y crear la relación de clave foránea. Verá que las columnas están indexadas como en la siguiente captura de pantalla:

ingrese la descripción de la imagen aquí

observe cómo se muestra zip_code en ambas tablas.

Chris Adams
fuente
1

Debe verificar que ambos sean iguales en todas sus propiedades, incluido en "Colación"

CrsCaballero
fuente
1

Yo estaba usando HeidiSQL y para resolver este problema tuve que crear un índice en la tabla referenciada con todas las columnas referenciadas.

agregar índice a la tabla Heidisql

Doug
fuente
Lo mismo para mí en mysql: InnoDB 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.
hendr1x
1

Me encontré con el mismo problema en este momento. En mi caso, todo lo que tuve que hacer es asegurarme de que la tabla a la que me refiero en la clave externa se debe crear antes de la tabla actual (anteriormente en el código). Entonces, si hace referencia a una variable (x * 5), el sistema debe saber qué es x (x debe declararse en líneas de código anteriores). Esto resolvió mi problema, espero que ayude a alguien más.

Alexander Nenartovich
fuente
He tenido el mismo problema en MariaDB v10.3.18. Usamos MySQL antes y advirtió que una clave foránea apuntaba a una tabla inexistente.
MarthyM
0

Tuve el mismo problema con el generador de esquemas de migración Laravel 5.1 con MariaDB 10.1.

El problema era que había escrito en unignedlugar de unsigned(els faltaba letra) al configurar la columna.

Después de corregir el error tipográfico se solucionó para mí.

Arda
fuente
0

Incluso me encontré con el mismo problema con mysql y liquibase. Entonces, este es el problema: la tabla desde la que desea hacer referencia a una columna de otra tabla es diferente, ya sea en el caso del tipo de datos o en términos de tamaño del tipo de datos.

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
fuente
0

Verifique que haya especificado el nombre de la tabla en el caso apropiado (si los nombres de la tabla distinguen entre mayúsculas y minúsculas en su base de datos). En mi caso tuve que cambiar

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

a

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

tenga en cuenta el customercambiado a CUSTOMER.

izogfif
fuente
0

O puede usar DBDesigner4 que tiene una interfaz gráfica para crear su base de datos y vincularlos usando FK. Haga clic derecho en su tabla y seleccione 'Copiar tabla Crear SQL' que crea el código.

ingrese la descripción de la imagen aquí

Diestro
fuente
0

Es un tema antiguo pero descubrí algo. Al construir un banco de trabajo MySQL, también obtiene las relaciones de la otra tabla. solo deja los pilares con los que te relacionas. Borrar otras columnas agregadas automáticamente. Esto funciona para mi.

Muhammed Alper Uslu
fuente
0

Mi caso fue que tenía un error tipográfico en la columna referida:

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

El mensaje de error es bastante críptico y he intentado todo: verificar los tipos de columnas, colaciones, motores, etc.

Me tomó un tiempo notar el error tipográfico y después de arreglarlo todo funcionó bien:

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
fuente
0

Me enfrento a este problema, el error vino cuando pones la clave primaria en diferentes tipos de datos como:

tabla 1:

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

Tabla 2:

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

el tipo de datos para la identificación de la segunda tabla debe ser incrementos

shaher11
fuente
0

El problema es muy simple de resolver.

por ejemplo: tiene dos tablas con nombres de usuarios y publicaciones y desea crear una clave externa en la tabla de publicaciones y usa phpMyAdmin

1) en la tabla de publicación agregue una nueva columna ( nombre : use_id | tipo : como el id en la tabla de usuario | Longitud : como el id en la tabla de usuario | Predeterminado : NULL | Atributos : sin firmar | índice: ÍNDICE)

2) en la pestaña Estructura, vaya a la vista de relación ( Nombre de restricción : configuración automática por phpmyAdmin | nombre de columna : seleccione id_usuario | tabla : usuarios | clave : id, ...)

Simplemente fue resuelto

javad mosavi irán / urmia

Javad mosavi
fuente