63 - Clave foránea.


Problema:

Trabajamos con las tablas "libros" y "editoriales" de una librería.

Eliminamos las tablas, si existen:

 drop table libros, editoriales;

Creamos las tablas:

 create table libros(
  codigo int unsigned auto_increment,
  titulo varchar(40) not null,
  autor varchar(30) not null default 'Desconocido',
  codigoeditorial tinyint unsigned not null,
  precio decimal(5,2) unsigned,
  cantidad smallint unsigned default 0,
  primary key (codigo)
 );

 create table editoriales(
  codigo tinyint unsigned auto_increment,
  nombre varchar(20) not null,
  primary key(codigo)
 );

En este ejemplo, el campo "codigoeditorial" de "libros" es una clave foránea, se emplea para enlazar la tabla "libros" con "editoriales".

Ingresamos algunos registros:

 insert into editoriales values(2,'Emece');
 insert into editoriales values(15,'Planeta');
 insert into editoriales values(23,'Paidos');

 insert into libros values(1,'El aleph','Borges',23,4.55,10);
 insert into libros values(2,'Alicia en el pais de las maravillas','Lewis Carroll'
                           ,2,11.55,2);
 insert into libros values(3,'Martin Fierro','Jose Hernandez',15,7.12,4);

Si modificamos el tipo, longitud o atributos de una clave foránea, ésta puede quedar inhabilitada para hacer los enlaces.

Veamos un ejemplo:

 alter table libros
  modify codigoeditorial char(1);

Veamos cómo afectó el cambio a la tabla "libros":

 select * from libros;

El libro con código de editorial "23" ("Paidos") ahora tiene "2" ("Emece") en "codigoeditorial" y el libro con código de editorial "15" ("Planeta") ahora almacena "1" (valor inexistente en "editoriales").

Si buscamos coincidencia de códigos en la tabla "editoriales":

 select l.titulo,e.nombre
  from libros as l
  join editoriales as e
  on l.codigoeditorial=e.codigo;

El resultado es erróneo.

Las claves foráneas y las claves primarias deben ser del mismo tipo para poder enlazarse. Si modificamos una, debemos modificar la otra para que los valores se correspondan.

Intentemos modificar la clave en "editoriales":

 alter table editoriales
  modify codigo char(1);

No lo permite porque si la modifica los valores para el campo clave quedan repetidos.




Retornar