MySQL Creando tablas con claves externas dando errno: 150

Resuelto asked hace 14 años • 0 respuestas

Estoy intentando crear una tabla en MySQL con dos claves externas, que hacen referencia a las claves principales en otras 2 tablas, pero recibo un errno: 150error 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;
 avatar Sep 22 '09 05:09
Aceptado

Estas condiciones deben cumplirse para no obtener el error 150 re ALTER TABLE ADD FOREIGN KEY:

  1. La tabla principal debe existir antes de definir una clave externa para hacer referencia a ella. Debe definir las tablas en el orden correcto: primero la tabla principal y luego la tabla secundaria. Si ambas tablas hacen referencia 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.

  2. Las dos tablas deben admitir restricciones de clave externa, es decir ENGINE=InnoDB. Otros motores de almacenamiento ignoran silenciosamente las definiciones de claves externas, por lo que no devuelven ningún error ni advertencia, pero la restricción FK no se guarda.

  3. Las columnas a las que se hace referencia en la tabla principal deben ser las columnas situadas más a la izquierda de una clave. Es mejor si la clave en Parent es PRIMARY KEYo UNIQUE KEY.

  4. La definición FK debe hacer referencia a las columnas PK en el mismo orden que la definición PK. Por ejemplo, si es FK REFERENCES Parent(a,b,c), entonces la PK principal no debe definirse en columnas en orden (a,c,b).

  5. 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 definirla UNSIGNEDpara 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 referencia VARCHAR(20)o viceversa.

  6. Cualquier columna FK de tipo cadena debe tener el mismo juego de caracteres y clasificación que las columnas PK correspondientes.

  7. Si ya hay datos en la tabla secundaria, cada valor de las columnas FK debe coincidir con un valor de las columnas PK de la tabla principal. Verifique esto con una consulta como:

     SELECT COUNT(*) FROM Child LEFT OUTER JOIN Parent ON Child.FK = Parent.PK 
     WHERE Parent.PK IS NULL;
    

    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.

  8. Ni la tabla principal ni la tabla secundaria pueden ser una TEMPORARYtabla.

  9. Ni la tabla principal ni la tabla secundaria pueden ser una PARTITIONEDtabla.

  10. Si declara un FK con la ON DELETE SET NULLopción, entonces las columnas FK deben ser anulables.

  11. Si declara un nombre de restricción para una clave externa, el nombre de la 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.

  12. Si hay otros FK en otras tablas que apuntan al mismo campo para el que está intentando crear el nuevo FK y están mal formados (es decir, una clasificación diferente), primero será necesario hacerlos consistentes. Esto puede ser el resultado de cambios pasados ​​en los que SET FOREIGN_KEY_CHECKS = 0;se utilizó una relación inconsistente definida por error. Consulte la respuesta de @andrewdotn a continuación para obtener instrucciones sobre cómo identificar estos FK problemáticos.

marv-el avatar Jan 12 '2011 20:01 marv-el

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 buscándolo LATEST FOREIGN KEY ERRORen el resultado.

Por ejemplo, este intento de crear una restricción de clave externa:

CREATE TABLE t1
(id INTEGER);

CREATE TABLE t2
(t1_id INTEGER,
 CONSTRAINT FOREIGN KEY (t1_id) REFERENCES t1 (id));

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 corre SHOW ENGINE INNODB STATUS;y te dirá:

------------------------
LATEST FOREIGN KEY ERROR
------------------------
130811 23:36:38 Error in foreign key constraint of table test/t2:
FOREIGN KEY (t1_id) REFERENCES t1 (id)):
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.

Dice que el problema es que no puede encontrar un índice. SHOW INDEX FROM t1muestra que no hay ningún índice para la tabla t1. Solucione eso, por ejemplo, definiendo una clave primaria en t1y la restricción de clave externa se creará exitosamente.

andrewdotn avatar Aug 12 '2013 05:08 andrewdotn

Asegúrese de que las propiedades de los dos campos que intenta vincular con una restricción sean exactamente iguales.

A menudo, la propiedad "sin firmar" en una columna de ID le sorprenderá.

ALTER TABLE `dbname`.`tablename` CHANGE `fieldname` `fieldname` int(10) UNSIGNED NULL;
Jon Winstanley avatar Oct 27 '2009 15:10 Jon Winstanley