Estoy tratando de crear una tabla en MySQL con dos claves externas, que hacen referencia a las claves primarias en otras 2 tablas, pero obtengo un error errno: 150 y no creará la tabla.
Aquí está el SQL para las 3 tablas:
CREATE TABLE role_groups (
`role_group_id` int(11) NOT NULL `AUTO_INCREMENT`,
`name` varchar(20),
`description` varchar(200),
PRIMARY KEY (`role_group_id`)
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `roles` (
`role_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50),
`description` varchar(200),
PRIMARY KEY (`role_id`)
) ENGINE=InnoDB;
create table role_map (
`role_map_id` int not null `auto_increment`,
`role_id` int not null,
`role_group_id` int not null,
primary key(`role_map_id`),
foreign key(`role_id`) references roles(`role_id`),
foreign key(`role_group_id`) references role_groups(`role_group_id`)
) engine=InnoDB;
Cualquier ayuda será muy apreciada.
mysql
foreign-keys
mysql-error-150
Bill Karwin
fuente
fuente
auto_increment
? Eso no es válido. Auto_increment es una palabra clave, no un identificador.Respuestas:
Tuve el mismo problema con
ALTER TABLE ADD FOREIGN KEY
.Después de una hora, descubrí que se deben cumplir estas condiciones para no obtener el error 150:
La tabla principal debe existir antes de definir una clave externa para hacer referencia a ella. Debe definir las tablas en el orden correcto: la tabla principal primero, luego la tabla secundaria. Si ambas tablas se referencian entre sí, debe crear una tabla sin restricciones FK, luego crear la segunda tabla y luego agregar la restricción FK a la primera tabla con
ALTER TABLE
.Las dos tablas deben admitir restricciones de clave externa, es decir
ENGINE=InnoDB
. Otros motores de almacenamiento ignoran silenciosamente las definiciones de clave externa, por lo que no devuelven ningún error o advertencia, pero la restricción FK no se guarda.Las columnas a las que se hace referencia en la tabla principal deben ser las columnas más a la izquierda de una clave. Mejor si la clave en el Padre es
PRIMARY KEY
oUNIQUE KEY
.La definición de FK debe hacer referencia a la (s) columna (s) PK en el mismo orden que la definición PK. Por ejemplo, si el FK
REFERENCES Parent(a,b,c)
, el PK principal no debe definirse en las columnas en orden(a,c,b)
.Las columnas PK de la tabla principal deben ser del mismo tipo de datos que las columnas FK de la tabla secundaria. Por ejemplo, si una columna PK en la tabla principal es
UNSIGNED
, asegúrese de definirUNSIGNED
para la columna correspondiente en el campo de la tabla secundaria.Excepción: la longitud de las cadenas puede ser diferente. Por ejemplo,
VARCHAR(10)
puede hacer referenciaVARCHAR(20)
o viceversa.Cualquier columna FK de tipo cadena debe tener el mismo conjunto de caracteres y colación que las columnas PK correspondientes.
Si ya hay datos en la tabla secundaria, todos los valores de la (s) columna (s) FK deben coincidir con un valor en la (s) columna (s) PK de la tabla principal. Verifique esto con una consulta como:
Esto debe devolver cero (0) valores no coincidentes. Obviamente, esta consulta es un ejemplo genérico; debe sustituir los nombres de sus tablas y columnas.
Ni la tabla principal ni la tabla secundaria pueden ser una
TEMPORARY
tabla.Ni la tabla principal ni la tabla secundaria pueden ser una
PARTITIONED
tabla.Si declara un FK con la
ON DELETE SET NULL
opción, entonces la (s) columna (s) FK deben ser anulables.Si declara un nombre de restricción para una clave externa, el nombre de restricción debe ser único en todo el esquema, no solo en la tabla en la que se define la restricción. Es posible que dos tablas no tengan su propia restricción con el mismo nombre.
Si hay otros FK en otras tablas que apuntan al mismo campo para el que está intentando crear el nuevo FK y tienen un formato incorrecto (es decir, una intercalación diferente), primero deberán ser coherentes. Esto puede ser el resultado de cambios pasados donde
SET FOREIGN_KEY_CHECKS = 0;
se utilizó con una relación inconsistente definida por error. Consulte la respuesta de @ andrewdotn a continuación para obtener instrucciones sobre cómo identificar estos problemas de FK.Espero que esto ayude.
fuente
int(11) unsigned NOT NULL
vsint(11) NOT NULL
.ON DELETE
regla de su CONSTRAINT es,SET NULL
asegúrese de que la clave externa pueda ser NULL. Pasé 30 minutos leyendo esta respuesta una y otra vez, asegurándome de que mis tablas cumplieran con las condiciones pero aún obteniendo el Error 150. Entonces noté que mi FK era un campo NO NULO, lo que significa que la regla era imposible de aplicar.El mensaje genérico "errno 150" de MySQL " significa que una restricción de clave externa no se formó correctamente ". Como probablemente ya sepa si está leyendo esta página, el mensaje de error genérico "errno: 150" es realmente inútil. Sin embargo:
Puede obtener el mensaje de error real ejecutando
SHOW ENGINE INNODB STATUS;
y luego buscandoLATEST FOREIGN KEY ERROR
en el resultado.Por ejemplo, este intento de crear una restricción de clave externa:
falla con el error
Can't create table 'test.t2' (errno: 150)
. Eso no le dice a nadie nada útil aparte de que es un problema de clave externa. Pero correSHOW ENGINE INNODB STATUS;
y te dirá:Dice que el problema es que no puede encontrar un índice.
SHOW INDEX FROM t1
muestra que no hay ningún índice para la tablat1
. Solucione eso, por ejemplo, definiendo una clave primaria activadat1
, y la restricción de clave externa se creará correctamente.fuente
SHOW ENGINE INNODB STATUS
me ayudó a identificar de inmediato un problema que había estado tratando de diagnosticar durante casi una hora. Gracias.SET FOREIGN_KEY_CHECKS = 0;
durante una importación / alteración que estaba mal formada en un momento u otro. Gran ayuda, gracias.Asegúrese de que las propiedades de los dos campos que intenta vincular con una restricción sean exactamente las mismas.
A menudo, la propiedad 'sin firmar' en una columna de ID lo sorprenderá.
fuente
¿Cuál es el estado actual de su base de datos cuando ejecuta este script? ¿Está completamente vacío? Su SQL funciona bien para mí cuando creo una base de datos desde cero, pero errno 150 generalmente tiene que ver con eliminar y recrear tablas que son parte de una clave externa. Tengo la sensación de que no está trabajando con una base de datos nueva y 100% nueva.
Si está cometiendo un error cuando "fuente" -ing su archivo SQL, debería poder ejecutar el comando "SHOW ENGINE INNODB STATUS" desde el indicador de MySQL inmediatamente después del comando "fuente" para ver información de error más detallada.
También puede consultar la entrada manual:
fuente
Para las personas que ven este hilo con el mismo problema:
Hay muchas razones para obtener errores como este. Para obtener una lista bastante completa de causas y soluciones de errores de clave externa en MySQL (incluidos los que se describen aquí), consulte este enlace:
Errores de clave externa de MySQL y Errno 150
fuente
Para otros que encuentran esta entrada SO a través de Google: asegúrese de que no está tratando de realizar una acción SET NULL en una columna de clave externa (a ser) definida como "NOT NULL". Eso me causó una gran frustración hasta que me acordé de hacer una COMPROBACIÓN DEL ESTADO DE INNODB DEL MOTOR.
fuente
Definitivamente no es el caso, pero este error me pareció bastante común y poco obvio. El objetivo de un
FOREIGN KEY
podría no serloPRIMARY KEY
. La respuesta que me resulta útil es:Una CLAVE EXTRANJERA siempre debe apuntar a un campo verdadero CLAVE PRIMARIA de otra tabla.
fuente
Como señaló @andrewdotn, la mejor manera es ver el error detallado (
SHOW ENGINE INNODB STATUS;
) en lugar de solo un código de error.Una de las razones podría ser que ya existe un índice con el mismo nombre, puede estar en otra tabla. Como práctica, recomiendo prefijar el nombre de la tabla antes del nombre del índice para evitar tales colisiones. por ejemplo, en lugar de
idx_userId
usaridx_userActionMapping_userId
.fuente
Asegúrese al principio de que
Tuve el mismo problema y lo solucioné. Tenía INT sin firmar para un campo y solo entero para otro campo.
fuente
Consejo útil, utilícelo
SHOW WARNINGS;
después de intentar suCREATE
consulta y recibirá el error, así como una advertencia más detallada:Entonces, en este caso, ¡es hora de volver a crear mi mesa!
fuente
Esto suele suceder cuando intenta crear un archivo en una base de datos existente. Suelta todas las tablas primero (o la propia base de datos). Y luego el archivo fuente con
SET foreign_key_checks = 0;
al principio ySET foreign_key_checks = 1;
al final.fuente
Encontré otra razón por la que esto falla ... nombres de tablas sensibles a mayúsculas y minúsculas.
Para esta definición de tabla
Esta definición de tabla funciona
mientras que este falla
El hecho de que funcionara en Windows y fallara en Unix me tomó un par de horas entenderlo. Espero que ayude a alguien más.
fuente
MySQL Workbench 6.3 para Mac OS.
Problema: errno 150 en la tabla X al intentar hacer ingeniería directa en un diagrama de base de datos, 20 de 21 tuvieron éxito, 1 falló. Si se eliminaron los FK en la tabla X, el error se movió a una tabla diferente que antes no fallaba.
Se cambió el motor de todas las tablas a myISAM y funcionó bien.
fuente
También vale la pena comprobar que no está operando accidentalmente en la base de datos incorrecta. Este error ocurrirá si la tabla externa no existe. ¿Por qué MySQL tiene que ser tan críptico?
fuente
Asegúrese de que las claves externas no aparezcan como únicas en el padre. Tuve este mismo problema y lo resolví demarcándolo como no único.
fuente
En mi caso, se debió al hecho de que el campo que era un campo de clave externa tenía un nombre demasiado largo, es decir.
foreign key (some_other_table_with_long_name_id)
. Prueba algo más corto. El mensaje de error es un poco engañoso en ese caso.Además, como @Jon mencionó anteriormente, las definiciones de campo deben ser las mismas (tenga cuidado con el
unsigned
subtipo).fuente
(Notas al margen demasiado grandes para un comentario)
No hay necesidad de una
AUTO_INCREMENT
identificación en una tabla de mapeo; desaste de eso.Cambie
PRIMARY KEY
a(role_id, role_group_id)
(en cualquier orden). Esto hará que los accesos sean más rápidos.Como probablemente desee mapear ambas direcciones, agregue también una
INDEX
con esas dos columnas en el orden opuesto. (No hay necesidad de hacerloUNIQUE
).Más consejos: http://mysql.rjweb.org/doc.php/index_cookbook_mysql#speeding_up_wp_postmeta
fuente
Cuando la restricción de clave externa se basa en el
varchar
tipo, además de la lista proporcionada pormarv-el
la columna de destino, debe haber una restricción única.fuente
ejecutar debajo de la línea antes de crear la tabla: SET FOREIGN_KEY_CHECKS = 0;
La opción FOREIGN_KEY_CHECKS especifica si se deben verificar o no las restricciones de clave externa para las tablas InnoDB.
- Especifique para verificar las restricciones de clave externa (este es el predeterminado)
- No verifique las restricciones de clave externa
SET FOREIGN_KEY_CHECKS = 0;
Cuándo usarlo: deshabilitar temporalmente las restricciones de referencia (establecer FOREIGN_KEY_CHECKS en 0) es útil cuando necesita volver a crear las tablas y cargar datos en cualquier orden padre-hijo
fuente
Encontré el mismo problema, pero comprobé que no tenía la tabla principal. Así que solo edito la migración principal frente a la migración secundaria. Simplemente hazlo.
fuente