MySQL - Error: 150 "Foreign key constraint is incorrectly formed"

 
Vista:

Error: 150 "Foreign key constraint is incorrectly formed"

Publicado por Daniel (1 intervención) el 23/09/2018 15:07:05
Tengo el siguiente código:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
CREATE TABLE IF NOT EXISTS pais(
id INT(16) AUTO_INCREMENT NOT NULL,
nombre VARCHAR(64) NOT NULL,
cod_pais INT(8) NOT NULL,
PRIMARY KEY (id,cod_pais)
);
 
CREATE TABLE IF NOT EXISTS provincia(
id INT(16) AUTO_INCREMENT NOT NULL,
nombre VARCHAR(64) NOT NULL,
cod_localidad INT(8) NOT NULL,
cod_pais INT(8) NOT NULL,
PRIMARY KEY (id,cod_localidad),
INDEX (cod_pais),
CONSTRAINT cod_pais_fk FOREIGN KEY (cod_pais) REFERENCES pais(cod_pais)
);


Y me da el siguiente error: Error: 150 "Foreign key constraint is incorrectly formed")


Estoy ejecutando el servidor MySQL (MariaDB) sobre Debian9.


Gracias.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
Imágen de perfil de xve
Val: 796
Oro
Ha mantenido su posición en MySQL (en relación al último mes)
Gráfica de MySQL

Error: 150 "Foreign key constraint is incorrectly formed"

Publicado por xve (1151 intervenciones) el 23/09/2018 19:14:23
Hola Daniel, por defecto, cuando creas una tabla, si no especificas lo contrario, utiliza el formato InnoDB, el cual no permite claves foraneas!!!

Para ello, tendrás que utilizar otro formato de tabla... por ejemplo MyISAM... para ello, tienes que añadir ENGINE=MyISAM al final:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
CREATE TABLE IF NOT EXISTS pais(
id INT(16) AUTO_INCREMENT NOT NULL,
nombre VARCHAR(64) NOT NULL,
cod_pais INT(8) NOT NULL,
PRIMARY KEY (id,cod_pais)
) ENGINE=MyISAM;
 
CREATE TABLE IF NOT EXISTS provincia(
id INT(16) AUTO_INCREMENT NOT NULL,
nombre VARCHAR(64) NOT NULL,
cod_localidad INT(8) NOT NULL,
cod_pais INT(8) NOT NULL,
PRIMARY KEY (id,cod_localidad),
INDEX (cod_pais),
CONSTRAINT cod_pais_fk FOREIGN KEY (cod_pais) REFERENCES pais(cod_pais)
) ENGINE=MyISAM;
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil
Val: 953
Oro
Ha mantenido su posición en MySQL (en relación al último mes)
Gráfica de MySQL

Error: 150 "Foreign key constraint is incorrectly formed"

Publicado por Leonardo Josué (414 intervenciones) el 24/09/2018 17:05:01
Hola Daniel (y xve):

Vamos aclarando algunas cosas que están mal. Por un lado xve nos comenta esto:

1
2
por defecto, cuando creas una tabla, si no especificas lo contrario, utiliza el formato InnoDB,
el cual no permite claves foraneas!!!

Tienes razón al decir que el formato por defecto que utiliza MySQL es InnoDB, pero estás equivocado al decir que estas tablas no permiten FK's, ya que el formato MyISAN es el que NO PERMITE LLAVES FORÁNTEAS

https://dev.mysql.com/doc/refman/8.0/en/myisam-storage-engine.html

1
2
3
Table 16.2 MyISAM Storage Engine Features
...
Foreign key support	No

Luego entonces, el error no va por ahí.

El problema es el siguiente: en tu tabla PAIS, estás definiendo una llave primaria COMPUESTA:

1
2
3
4
CREATE TABLE IF NOT EXISTS pais(
...
PRIMARY KEY (id,cod_pais)
...


Entonces, cuando quieras hacer referencia a esta tabla COMO UNA LLAVE FORÁNEA ES NECESARIO QUE ESA LLAVE FORÁNEA TAMBIÉN SEA COMPUESTA. En sentencia sólo estás considerando el campo COD_PAIS, por lo tanto es necesario agregar un campo para el ID (no necesarioamente se tienen que llamar igual, pero es una buena práctica, no poner campos llamados sólo ID en cada tabla. Entonces, podrías hacerlo así:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
CREATE TABLE IF NOT EXISTS pais(
  id INT(16) AUTO_INCREMENT NOT NULL,
  nombre VARCHAR(64) NOT NULL,
  cod_pais INT(8) NOT NULL,
  PRIMARY KEY (id,cod_pais)
);
 
CREATE TABLE IF NOT EXISTS provincia(
  id INT(16) AUTO_INCREMENT NOT NULL,
  nombre VARCHAR(64) NOT NULL,
  cod_localidad INT(8) NOT NULL,
  id_pais INT(16) NOT NULL,
  cod_pais INT(8) NOT NULL,
  PRIMARY KEY (id,cod_localidad),
  INDEX (cod_pais),
  CONSTRAINT cod_pais_fk FOREIGN KEY (id_pais, cod_pais) REFERENCES pais(id, cod_pais)
);

Observa que la llave FORANEA queda entonces compuesta de dos campos (como en la tabla padre):

1
CONSTRAINT cod_pais_fk FOREIGN KEY (id_pais, cod_pais) REFERENCES pais(id, cod_pais)


O mejor aun, haciendo uso de mejores prácticas, renombras tus campos ID's para agregarles a qué tabla pertenecen y así los nombres quedan exactamente iguales en las referencias:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mysql> CREATE TABLE IF NOT EXISTS pais(
    ->   id_pais INT(16) AUTO_INCREMENT NOT NULL,
    ->   cod_pais INT(8) NOT NULL,
    ->   nombre VARCHAR(64) NOT NULL,
    ->   PRIMARY KEY (id_pais, cod_pais)
    -> ) ENGINE=INNODB;
Query OK, 0 rows affected (0.20 sec)
 
mysql>
mysql> CREATE TABLE IF NOT EXISTS provincia(
    ->   id_provincia INT(16) AUTO_INCREMENT NOT NULL,
    ->   cod_provincia INT(8) NOT NULL,
    ->   nombre VARCHAR(64) NOT NULL,
    ->   id_pais INT(16) NOT NULL,
    ->   cod_pais INT(8) NOT NULL,
    ->   PRIMARY KEY (id_provincia,cod_provincia),
    ->   INDEX (cod_pais),
    ->   CONSTRAINT cod_pais_fk FOREIGN KEY (id_pais, cod_pais) REFERENCES pais(id_pais, cod_pais)
    -> ) ENGINE=INNODB;
Query OK, 0 rows affected (0.27 sec)

Observa que ambas tablas quedan como tipo InnoDB sin ningún problema.

Haz la prueba y nos comentas.

Saludos
Leo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
Imágen de perfil de xve
Val: 796
Oro
Ha mantenido su posición en MySQL (en relación al último mes)
Gráfica de MySQL

Error: 150 "Foreign key constraint is incorrectly formed"

Publicado por xve (1151 intervenciones) el 24/09/2018 19:30:49
Gracias por comentarlo Leonardo... sabia que con uno de los dos formatos no se podia, pero no verifique!!!!

Gracias por las grandes aclaraciones que haces!!!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar