martes, 8 de marzo de 2016

Error "Supports transactions, row-level locking, and foreign keys" al intentar crear clave foránea en MySQL

Ésta es como una nota mental o algo así, porque después de perder un buen rato resolviendo este problema y sabiendo que la solución era tan simple y no encontré la respuesta puntual en Internet, siento la necesidad de dejar el recordatorio, no sea que vuelva a pasar en un futuro.

Contexto:

Intentar crear una clave foránea entre dos tablas en MySQL 5, usando una sentencia como la siguiente:

ALTER TABLE tabla1 ADD CONSTRAINT `FK_tabla1_tabla2_id` FOREIGN KEY (tabla2_id) REFERENCES tabla2(id) ON DELETE RESTRICT ON UPDATE CASCADE;

Al ejecutar la sentencia aparece un error como el siguiente (en phpMyAdmin):

#1005 - Can't create table 'db_test.#sql-51c_d7f' (errno: 150) 

Lo cual para MySQL es la siguiente advertencia:

Supports transactions, row-level locking, and foreign keys


Puntos a revisar:
  • Que el nombre de la clave no esté repetido: correcto
  • Que el nombre del campo y la tabla destino y origen estén bien: correcto
  • Que ambas tablas sean InnoDB: correcto
  • Que ambos campos sean del mismo tamaño: correcto
  • ... muchas más pruebas desesperadas: correcto

... y la solución real: 


Puede parecer sencillo pero verla, por lo simple, fue una odisea. El campo origen (tabla1.tabla2_id) NO ERA UNSIGNED mientras que el campo destino SI lo era :'(

Un error sutil pero que hace que ambos campos no sean idénticos y por ende no puedan compartir una clave foránea. Solución: modificar el campo origen para hacerlo no signado (UNSIGNED) y que de esa manera ambos campos sean completamente idénticos.