Sei sulla pagina 1di 21

Claves primarias, claves forneas, ndices

En la teora de bases de datos, se llama clave primaria a un campo, o a una


combinacin de campos, que identifica en forma nica a cada registro, y
una clave fornea es una referencia, en una tabla, a la clave primaria de otra
tabla. Por ejemplo, en una factura necesitamos identificar para qu cliente se ha
hecho la factura.
Por ejemplo, para una tabla de clientes se podra usar, como clave primaria, una
de las siguientes opciones:
La cdula de identidad del cliente.
La combinacin de nombre y apellido. Esto es dudoso, ya que un dos
clientes pueden tener el mismo nombre y el mismo apellido.
Un cdigo de cliente, asignado por la empresa.
Sin embargo, lo ms recomendable es utilizar un nmero que nunca ver el
usuario final. Para este fin, se necesita un nmero secuencial. Esto nos trae
numerosas ventajas, entre otras:
Se simplifican las claves forneas y las relaciones entre las tablas. Por
ejemplo, si para identificar a un cliente utilizamos la combinacin de
nombre y apellido, tambin necesitamos el nombre y el apellido del cliente
en la factura, para identificar al cliente.
Se ahorra espacio, ya que un campo de tipo Integer (entero) slo utiliza 4
bytes (sin embargo, permite nmeros hasta 2 mil millones). Se puede
argumentar que se necesita un campo ms para la clave primaria; pero se
ahorra espacio en las claves forneas en otras tablas.
El acceso a los datos es ms rpido. Esto est directamente relacionado
con el hecho de que los campos de tipo Integer (y sus ndices
correspondientes) son ms pequeos.
El usuario puede cambiar los cdigos, sin que se tengan que "propagar" los
cambios a otras tablas.
Tambin hay algunas desventajas; sobre todo, la programacin se hace ms
complicada en algunos casos. Pero he visto en la prctica que es un sacrificio que
vale la pena.
Ahora, explicar los detalles de cmo implementar estas claves "internas".
Desafortunadamente, en Visual FoxPro no se puede simplemente marcar un
campo como "auto-incrementado" (como se lo hara en Access), pero no es muy
complicado lograr lo mismo en Visual FoxPro.
Para guardar los nmeros secuenciales (y as saber cul es el siguiente
nmero que se debe asignar a cada nuevo registro), se crea una tabla que
se llama "serialnumber", con dos campos: "sequence", tipo Character(30),
y "nextnum", tipo Integer. Es conveniente (pero no urgente) que la tabla
sea parte de una base de datos (slo as puede participar en transacciones,
lo cual permite anular cambios).
Para la clave primaria, se utiliza un campo de tipo Integer (ver Nuevos
tipos de datos). Por ejemplo, en la tabla "cliente", se puede tener un campo
que tambin se llama "cliente", de tipo Integer.
En ese campo de clave primaria, se entra a "Default", y se escribe la
siguiente expresin: serialnumber("cliente").
Esto invocar una funcin "serialnumber". Yo prefiero almacenar la
funcin en los procedimientos almacenados de la base de datos. La
funcin es:
**********************************************************************
FUNCTION SERIALNUMBER(tnSequence)
* Conseguir nmero secuencial. Usado para generar claves primarias.
local lnSelect
lnSelect = select()
if used("serialnumber")
select serialnumber
else
select 0
use serialnumber
endif
set order to "sequence"
seek padr(tnSequence, len(sequence))
if not found()
append blank
replace sequence with tnSequence, nextnum with 1
endif
local lnReturnValue
if lock()
lnReturnValue = nextnum
replace nextnum with nextnum + 1
else
lnReturnValue = -1
endif
unlock
select (lnSelect)
return lnReturnValue
Para definir una clave primaria en una tabla, se tiene que crear un ndice con una
expresin que tiene que ser nica. Luego, se define el ndice como clave primaria
("Primary"). Esto se lo hace directamente en la definicin de la tabla (modify
structure). Por ejemplo, en la tabla cliente, se crea un ndice por el campo cliente.
La forma ms rpida de hacer sto es indicar, en la misma lista de campos, que se
quiere tener un ndice sobre ese campo (siempre debe ser "ascending"). Luego,
en la pgina de ndices se lo marca como "Primary".
Se puede asegurar que otras combinaciones de campos sean nicas. Slo puede
haber una clave primaria en una tabla, pero se pueden marcar otros ndices como
"Candidate". En otros sistemas de base de datos, esto se llamara "Unique";
desafortunadamente, en FoxPro esta palabra ya ha sido reservado para algo
distinto. Recomiendo no utilizar nunca ndices del tipo "Unique" en Visual
FoxPro; lo que estos ndices logran, mejor se puede lograr con otros mtodos.
Digamos que Visual FoxPro incluye ndices de tipo "Unique" por mantener la
compatibilidad con FoxPro.
Si se quiere garantizar unicidad, puede haber un problema con registros borrados:
el usuario borra un cliente, digamos que tiene el cdigo (campo cod_cliente)
"X1", luego agrega otro registro e intenta poner el mismo cdigo. Visual FoxPro
dir que el registro ya existe. Se puede solucionar esto eliminando permanente el
registro borrado (con la orden PACK), pero esto no es muy prctico. Es mejor
crear el ndice filtrado, con la condicin: NOT DELETED().













Leccin 14 - Relaciones, claves primarias
y forneas

Las Relaciones es lo que, aparte de dar el nombre a las BD relacionales, hacen de este modelo
una potente herramienta de reunin de datos. Para abordar las relaciones debemos tratar
primero el concepto de clave primaria y clave fornea, puesto que son estas claves las que
establecen las relaciones en una BD, y realizan la reunin de datos mediante consultas SQL.

Clave primaria
Si usted recuerda como su profesor de enseanza bsica pasaba lista a la clase, recordar que
nombraba a los alumnos bien por su apellido, bien por su nombre, dependiendo del caso, e
incluso por nombre y apellido si era necesario evitar ambigedades. El propsito era dejar claro a
quien se estaba haciendo mencin y no dar lugar a dudas entre dos alumnos de igual nombre o
apellido. Podramos decir que el profesor asignaba una clave primaria a cada alumno, y con ello
todo el mundo saba que clave identificar como propia y responder: presente, al orla.

Podemos considerar que una tabla es como una clase, y el conjunto de registros que contiene son
los alumnos de esta clase. Para identificar cada registro es necesario establecer, de igual modo
que hace el profesor, una clave primaria, con el propsito de identificar cada registro de forma
nica, por lo que el valor, o valores que ejercen de clave en un registro no se pueden repetir en
el resto de registros de la tabla, ni en futuros registros que puedan existir. De esto ya se encarga
el SGBD al especificarle que campos de la tabla forman la clave primaria, devolviendo un error
cuando se intenta duplicar una clave primaria al insertar un nuevo registro en la tabla.

Un error comn, a mi entender, al establecer la clave primaria de una tabla es intentar
aprovechar algn campo de datos para que ejerza de clave, por ejemplo el DNI(documento
nacional de identidad) de una persona. Aparentemente es un campo que no se puede repetir y,
por tanto, es un buen candidato para ejercer de clave primaria en, por ejemplo , una tabla de
empleados o de alumnos. Sin embargo no tenemos control sobre l, es decir, no podemos
garantizar que no se repita. En ocasiones se asigna un DNI que perteneci a una persona ya
fallecida, a un nuevo ciudadano de modo que aunque sea una posibilidad remota, puede dar
problemas. Eso sin considerar que en ocasiones pueda resultar una clave poco prctica de
manejar.

Otro error comn es pretender que el campo clave guarde informacin implcita en la propia
clave. Por ejemplo, a un vehculo de nuestra flota le asignamos la clave 1100456, donde el 11
est indicando que es marca SEAT y el 00456 es el resto de la clave.

Mi consejo es que no se empee, ni en aprovechar datos para que ejerzan de clave, ni en
aprovechar claves para que implcitamente contengan informacin relevante. Las claves son
claves y deben disearse nicamente para identificar registros. Los nmeros naturales (1, 2 , 3 ,
etc...) son excelentes candidatos para ejercer de clave, se pueden ordenar (el SGBD crear
ndices sobre los campos clave que agilizarn las consultas) y son infinitos (siempre dispondremos
de un valor para no repetir claves).

Clave fornea
La clave o claves forneas de una tabla son referencias a registros de otra tabla, formndose
entre ambas tablas una relacin. Una registro de la tabla que tiene la clave fornea, llamemoslo
registro hijo, apunta a un solo registro de la tabla a la que hace referencia, llamemoslo registro
padre. Por tanto, una clave fornea apuntar siempre a la clave primaria de otra tabla.
De hecho el nombre ya nos indica que es una clave externa, es decir, el valor que contiene un
registro en el campo, o campos, que ejercen de clave fornea, deber contenerlo algn
registro(uno solo) en el campo, o campos, que ejercen de clave primaria en la tabla a la que hace
referencia dicha clave fornea.

Es tambin el SGBD quien garantiza esto, no dejando armar una clave fornea si pretendemos
montarla sobre el campo, o campos, que no son clave primaria en la tabla con la que se pretende
relacionar.
Tampoco permitir, devolviendo un error, insertar valores que no existen como clave primaria en
la tabla padre, o tabla a la que se hace referencia. A esto se le llama integridad referencial. El
SGBD no permite incoherencias referenciales, de modo que si por ejemplo se intenta eliminar un
registro padre el cual dejara hijos hurfanos en otras tablas, es decir, tiene referencias o claves
forneas de l, el SGBD devuelve un error y no se realiza la operacin.

Relaciones
El modo de relacionar registros entre tablas es por tanto mediante referencias, para lo cual se
usan los identificadores definidos como claves primarias y forneas.

Supongamos una academia donde se imparten clases, en consecuencia habr cursos, profesores y
alumnos. En nuestra base de datos diseamos una tabla para cada entidad, es decir, para
alumnos, profesores y cursos. Veamos como se relacionan entre si estas tres entidades y como se
establecen estas relaciones en la base de datos.

Intuitivamente usted puede resolver la siguiente relacin: La academia oferta cursos que
imparten los profesores a los alumnos matriculados, y est en lo cierto, pero para relacionar esto
en una BD debemos conocer en que medida se relacionan entre si estas tres entidades, es lo que
se llama cardinalidad de una relacin. Veamos primero el diseo de las tablas, los datos que
contienen, y que campo, o campos, juegan el papel de identificador o clave primaria.
Los campos clave se han bautizado con el prefijo ID, abreviacin de identificador.

TABLA CURSOS


TABLA PROFESORES


TABLA ALUMNOS


A estas tablas se las llama "maestros", dado que contienen informacin relevante y concreta de
cada entidad, as hablaremos del maestro de profesores o del maestro de alumnos. Bien, para
establecer las relaciones entre estas tres tablas necesitamos conocer con algo ms de detalle la
actividad en la academia, de modo que despus de investigar un poco sacamos las siguientes
conclusiones:
Cada curso lo imparte un nico profesor, sin embargo algn profesor imparte ms de un
curso.
Cada curso tiene varios alumnos, y algunos alumnos cursan dos o ms cursos.

* * *

Relacin de cardinalidad 1 a N

Establezcamos la siguiente relacin:

Cada curso lo imparte un nico profesor, sin embargo algn profesor imparte ms de un curso.

Para ello basta con crear un campo en la tabla CURSOS que informe que profesor lo imparte. Este
dato es una clave primaria de la tabla PROFESORES alojada en la tabla CURSOS, de ah lo de clave
fornea, por tanto el campo que ejercer de clave fornea en la tabla CURSOS debe ser
forzosamente una referencia a la clave primaria de la tabla PROFESORES.
Este tipo de relacin se denomina de uno a varios, tambin denominada de 1 a N: un profesor
imparte varios cursos, pero un curso es impartido por un nico profesor. En estos casos siempre
se disea una clave fornea en la tabla hijo(CURSOS) que apunta a la tabla padre(PROFESORES).

Debemos disear entonces una clave fornea en la tabla CURSOS para alojar valores que son
clave primaria de la tabla PROFESORES. En este caso disearemos un campo que llamaremos
ID_PROFE, aunque se podra llamar de cualquier otro modo, que contendr el identificador de
profesor que imparte el curso que representa cada registro. Veamos como queda la tabla
CURSOS:



Observando los datos de la tabla se aprecia como efectivamente cada curso lo imparte un nico
profesor, y que algn profesor imparte ms de un curso. Tambin se observa como uno de los
curso no se le ha asignado profesor, dado que el campo ID_PROFE esta a nulo. Por lo tanto una
clave fornea apuntar a un solo registro de la tabla padre o no apuntar a ninguno, en cuyo caso
guardar un valor indeterminado o nulo, pero jams contendr un valor que no exista en la tabla
padre.

A usted se le puede ocurrir que es mucho ms prctico y simple guardar para cada curso el
nombre del profesor en lugar de claves que apenas nos dicen nada a simple vista. Esto sera
transgredir la filosofa de las BD relacionales, que defienden la no duplicidad de informacin. El
nombre de un profesor debe estar en el maestro de profesores, y cualquier referencia a ellos
debe hacerse mediante su identificador. Con ello conseguimos tres cosas destacables:
No se duplica informacin en la BD.
Cualquier cambio o correccin de esa informacin solo debe realizarse en un nico lugar.
Evitamos la ambigedad al no llamar la misma cosas de mil formas distintas en mil
ubicaciones posibles.

Veamos la consulta que reune el nombre de cada profesor junto al curso que imparte.
CDIGO: SELECCIONAR TODO
select *
from CURSOS C, PROFESORES P
where C.ID_PROFE = P.ID_PROFE
llevar cdigo al banco de pruebas




Observe como si omitimos la clusula WHERE de la anterior consulta, el SGBD realizara el producto
cartesiano entre los cursos y los profesores, es decir, asociara todos los profesores con todos los
cursos. El hecho de disponer de un indicador por cada curso que informa que profesor lo imparte,
permite filtrar el producto cartesiano y solicitar aquellas filas que la columna ID_PROFE procedente de
la tabla cursos es igual a la columna ID_PROFE procedente de la tabla PROFESORES, discriminando as
las filas del producto cartesiano que carecen de sentido y obteniendo aquellas que guardan una
relacin.


Una lista de esto mismo mejor presentada:
CDIGO: SELECCIONAR TODO
select concat('Curso de ',C.TITULO,', impartido por ',P.NOMBRE,' ',P.APELLI
DOS) CURSOS
from CURSOS C, PROFESORES P
where C.ID_PROFE = P.ID_PROFE
llevar cdigo al banco de pruebas



Las relaciones de 1 a N son quizs las ms comunes en una BD y pueden verse como un padre,
tabla referenciada, con muchos hijos, tabla que hace referencia a este padre. En el caso que se
acaba de tratar el padre es el profesor y los hijos son los cursos que imparte dicho profesor. Todo
hijo tiene forzosamente un padre, a no ser que la clave fornea pueda contener valores nulos,
mientras que un padre puede tener de cero a muchos hijos.
* * *

Relacin de cardinalidad N a M
Establezcamos la siguiente relacin:

Cada curso tiene varios alumnos, y algunos alumnos cursan dos o ms cursos.

Esta relacin es un poco ms laboriosa de establecer en la base de datos, puesto que un alumno
cursa varios cursos, y a su vez, un curso es cursado por varios alumnos. Este tipo de relacin se
denomina de varios a varios, o bien, de N a M. Necesitamos crear una nueva tabla denominada
tabla de relacin, y que tiene como propsito definir la relacin de N a M. La nueva tabla:
ALUMNOS_CURSOS, contendr como mnimo las claves primarias de ambas tablas: ID_ALUMNO e
ID_CURSO. La clave primaria de la nueva tabla la formaran ambos campos conjuntamente, y a su
vez cada uno de ellos por separado ser clave fornea de la tabla ALUMNOS y CURSOS
respectivamente.

Echemos un vistazo a la tabla ALUMNOS_CURSOS:


Fijese que esta tabla contiene nicamente referencias. Cada registro establece una relacin, est
relacionando un registro de la tabla CURSOS con un registro de la tabla ALUMNOS.

Veamos la consulta que realiza la reunin de los alumnos con los cursos que cursa cada uno:
CDIGO: SELECCIONAR TODO
select *
from ALUMNOS_CURSOS AC, ALUMNOS A, CURSOS C
where AC.ID_ALUMNO = A.ID_ALUMNO
and AC.ID_CURSO = C.ID_CURSO
llevar cdigo al banco de pruebas



Una lista de esto mismo mejor presentada:
CDIGO: SELECCIONAR TODO
select C.TITULO CURSO , concat(A.APELLIDOS,', ',A.NOMBRE ) ALUMNO
from ALUMNOS_CURSOS AC, ALUMNOS A, CURSOS C
where AC.ID_ALUMNO = A.ID_ALUMNO
and AC.ID_CURSO = C.ID_CURSO
order by C.TITULO , A.NOMBRE , A.APELLIDOS
llevar cdigo al banco de pruebas




En este caso tambin podemos hacer el ejercicio de considerar el producto cartesiano entre estas tres
tablas y como la clusula WHERE permite ignorar aquellos registros del producto cartesiano que
carecen de sentido y filtrar aquellos que guardan una relacin.


La tabla de relacin puede contener ms informacin si es necesario, siempre y cuando la
informacin sea vinculante tanto para el curso como para el alumno del registro en cuestin. No
se tercia guardar aqu datos referentes al alumno que no tengan que ver con el curso, o datos del
curso que no tengan que ver con el alumno. Por tanto registrar aqu cosas como la fecha de
matrcula de un alumno en un curso, o la nota que el alumno ha sacado en un curso, tiene
sentido, mientras que no lo tiene guardar aqu la fecha en que empieza un curso que nada tiene
que ver con un alumno, o la veterana del alumno en la academia que nada tiene que ver con un
curso.
* * *

Relacin de cardinalidad 1 a 1
No vamos a extendernos en esta tipo de relacin puesto que no suelen darse mucho. En cualquier
caso estas relaciones pueden verse como una relacin 1 a N donde la N vale uno, es decir como
una relacin padre hijos donde el hijo es hijo nico. En estos casos, cuando slo se espera un hijo
por registro padre, podemos montar la clave fornea en cualquiera de las dos tablas, aunque lo
ms correcto es establecerla en la tabla que NO es maestro. A efectos prcticos lo mismo da que
el padre a punte al hijo que, a la inversa, es decir, que el hijo apunte al padre, o si usted quiere,
cual de las dos tablas juega el papel de padre y cual de hijo. Lo importante es saber como se ha
establecido la relacin para atacarla mediante SQL al construir las consultas, pero siempre es
preferible que la tabla maestro juegue el papel de padre.
* * *

Resumen
La clave primaria de una tabla permiten identificar registros de forma nica, estas pueden ser
simples: de un solo campo, o bien compuestas: formadas por dos o ms campos. En cualquier
caso los valores que toman estas claves no se pueden repetir en dos o ms registros de la tabla,
puesto que se perdera la funcionalidad de identificar un registro de forma nica. De esto se
encarga el SGBD si se ha especificado debidamente que campos son la clave primaria de la tabla.

Las claves forneas de una tabla permiten establecer relaciones con otras tablas, puesto que
contienen valores que encontramos como clave primaria en la tabla con la que se relaciona. Una
clave fornea ser simple o compuesta dependiendo de si lo es la clave primaria de la tabla a la
que apunta o hace referencia.

Si al disear una tabla el campo o campos que forman una clave fornea pueden contener valores
nulos, entonces el registro hijo puede no tener registro padre asociado. Esto es muy comn que
ocurra cuando un registro se ha creando en previsin y ser en un futuro, despus de que ocurra
alguna cosa, que se le asignar un padre. Por ejemplo el curso sin profesor definido de la tabla
CURSOS. El curso est previsto que se imparta, pero no se ha decidido o no se conoce aun que
profesor lo impartir, de ah que el campo ID_PROFE de dicho registro contenga un valor nulo.

Las relaciones de 1 a N son quizs las que ms se dan en una BD, en estos casos siempre
encontraremos la clave fornea en el registro hijo apuntando al registro padre.

Las relaciones de N a M, entre por ejemplo dos tablas maestras, siempre necesitar una
estructura auxiliar para establecer la relacin. Esta tabla auxiliar se denomina tabla de relacin,
y contendr como mnimo los campos que son clave primaria en ambos maestros. La clave
primaria de la nueva tabla ser siempre compuesta y estar formada por todos estos campos que
son clave primaria en los maestros. A su vez estos campos por separado sern clave fornea de
sus respectivos maestros. Por tanto los registros hijos se hallarn en la tabla de relacin.

El modo de obtener la reunin de tablas relacionadas es mediante filtros sobre el producto
cartesiano de dichas tablas, excluyendo con ayuda de la clusula WHERE aquellos registros del
producto cartesiano que carecen de sentido y obteniendo los que guardan una relacin. Para ello
debemos igualar la clave primaria de la tabla padre con la clave fornea de la tabla hijo.
* * *

Ejercicio 1
Construya una consulta que devuelva los cursos en que se ha matriculado el alumno con
identificador 1.

Modifique la anterior consulta para que devuelva los nombres y apellidos de los alumnos, y los
cursos en que se han matriculado, tales que el nombre de pila del alumno contenga un E.

Ejercicio 2
Cuantos cursos imparte cada profesor? Construya una consulta que responda a esta cuestin de
modo que el resultado muestre el nombre completo del profesor acompaado del nmero de
cursos que imparte.

Ejercicio 3
Cuantos alumnos hay matriculados en cada uno de los cursos? Construya una consulta que
responda a esta cuestin de modo que el resultado muestre el titulo del curso acompaado de el
nmero de alumnos matriculados.

Modifique la anterior consulta de modo que muestre aquellos cursos que el nmero de alumnos
matriculados sea exactamente de dos alumnos.

Ejercicio 4
Si ahora a usted le pidiesen que adaptara la BD, que consta de las tres tablas presentadas en esta
leccin, a la siguiente necesidad: A todo alumno se le asignara un profesor que lo tutele. Que
cambios realizara en la BD?








Este curso est sujeto a la licencia Reconocimiento-NoComercial-SinObraDerivada 3.0 de Creative
Commons. Usted puede copiarla, distribuirla y comunicarla pblicamente siempre que especifique su
autor y deletesql.com; no la utilice para fines comerciales; y no haga con ella obra derivada. Puede
usted consultar la licencia completa aqu.
Llaves Primarias y Foraneas

Claves primarias
Para entender lo que son las claves forneas, tal vez sea necesario entender primero lo que son
las claves primarias.
Es un hecho que las claves juegan un papel muy importante no slo en MySQL, sino en cualquier
base de datos relacional. De manera simple, las claves proporcionan una manera rpida y eficiente
de buscar datos en una tabla, adems de que permiten preservar la integridad de los datos.
Una clave candidata es un campo, o una combinacin de campos, que identifican de manera
nica un registro de una tabla. stas no pueden contener valores nulos, y su valor debe ser nico.
Una clave primaria es una clave candidata que ha sido diseada para identificar de manera nica
a los registros de una tabla a travs de toda la estructura de la base de datos.
La seleccin de una clave primaria es muy importante en el diseo de una base de datos, ya que
es un elemento clave de los datos que facilita la unin de tablas y el concepto total de una base de
datos relacional.
Las claves primarias deben ser nicas y no nulas, de manera que garanticen que una fila de una
tabla pueda ser siempre referenciada a travs de su clave primaria.
MySQL requiere que se especifique NOT NULL para las columnas que se van a utilizar como
claves primarias al momento de crear una tabla.

Claves forneas e integridad referencial
Podemos decir de manera simple que integridad referencial significa que cuando un registro en
una tabla haga referencia a un registro en otra tabla, el registro correspondiente debe existir. Por
ejemplo, consideremos la relacin entre una tabla cliente y una tabla venta.
+------------+ +-------------+
| cliente | | venta |
+------------+ +-------------+
| id_cliente | | id_factura |
| nombre | | id_cliente |
+------------+ | cantidad |
+-------------+
Para poder establecer una relacin entre dos tablas, es necesario asignar un campo en comn a
las dos tablas. Para este ejemplo, el campo id_cliente existe tanto en la tabla cliente como en la
tabla venta. La mayora de las veces, este campo en comn debe ser una clave primaria en alguna
de las tablas. Vamos a insertar algunos datos en estas tablas.
Tabla cliente
+------------+--------------+
| id_cliente | nombre |
+------------+--------------+
| 1 | Juan penas |
| 2 | Pepe el Toro |
+------------+--------------+

Tabla venta
+------------+------------+----------+
| id_factura | id_cliente | cantidad |
+------------+------------+----------+
| 1 | 1 | 23 |
| 2 | 3 | 39 |
| 3 | 2 | 81 |
+------------+------------+----------+
Hay dos registros en la tabla cliente, pero existen 3 id_cliente distintos en la tabla venta. Habamos
dicho que las dos tablas se relacionan con el campo id_cliente, por lo tanto, podemos decir que
Juan Penas tiene una cantidad de 23, y Pepe el Toro 81, sin embargo, no hay un nombre que se
corresponda con el id_cliente 3.
Las relaciones de claves forneas se describen como relaciones padre/hijo (en nuestro ejemplo,
cliente es el padre y venta es el hijo), y se dice que un registro es hurfano cuando su padre ya no
existe.
Cuando en una base de datos se da una situacin como esta, se dice que se tiene una integridad
referencial pobre (pueden existir otra clase de problemas de integridad). Generalmente esto va
ligado a un mal diseo, y puede generar otro tipo de problemas en la base de datos, por lo tanto
debemos evitar esta situacin siempre que sea posible.
En el pasado, MySQL no se esforzaba en evitar este tipo de situaciones, y la responsabilidad
pasaba a la aplicacin. Para muchos desarrolladores, esta no era una situacin del todo grata, y
por lo tanto no se consideraba a MySQL para ser usado en sistemas "serios". Por supuesto, esta
fue una de las cosas ms solicitadas en las anteriores versiones de MySQL; que se tuviera soporte
para claves forneas, para que MySQL mantenga la integridad referencial de los datos.
Una clave fornea es simplemente un campo en una tabla que se corresponde con la clave
primaria de otra tabla. Para este ejemplo, el campo id_cliente en la tabla venta es la clave fornea.
Ntese que este campo se corresponde con el campo id_cliente en la tabla cliente, en dnde este
campo es la clave primaria.
Las claves forneas tienen que ver precisamente con la integridad referencial, lo que significa que
si una clave fornea contiene un valor, ese valor se refiere a un registro existente en la tabla
relacionada.


Claves forneas en MySQL


Estrictamente hablando, para que un campo sea una clave fornea, ste necesita ser definido
como tal al momento de crear una tabla. Se pueden definir claves forneas en cualquier tipo de
tabla de MySQL, pero nicamente tienen sentido cuando se usan tablas del tipo InnoDB.
A partir de la versin 3.23.43b, se pueden definir restricciones de claves forneas con el uso de
tablas InnoDB. InnoDB es el primer tipo de tabla que permite definir estas restricciones para
garantizar la integridad de los datos.
Para trabajar con claves forneas, necesitamos hacer lo siguiente:
Crear ambas tablas del tipo InnoDB.
Usar la sintaxis FOREIGN KEY(campo_fk) REFERENCES nombre_tabla (nombre_campo)
Crear un ndice en el campo que ha sido declarado clave fornea.
InnoDB no crea de manera automtica ndices en las claves forneas o en las claves
referenciadas, as que debemos crearlos de manera explcita. Los ndices son necesarios para que
la verificacin de las claves forneas sea ms rpida. A continuacin se muestra como definir las
dos tablas de ejemplo con una clave fornea.
CREATE TABLE cliente
(
id_cliente INT NOT NULL,
nombre VARCHAR(30),
PRIMARY KEY (id_cliente)
) TYPE = INNODB;

CREATE TABLE venta
(
id_factura INT NOT NULL,
id_cliente INT NOT NULL,
cantidad INT,
PRIMARY KEY(id_factura),
INDEX (id_cliente),
FOREIGN KEY (id_cliente) REFERENCES cliente(id_cliente)
) TYPE = INNODB;
La sintaxis completa de una restriccin de clave fornea es la siguiente:
[CONSTRAINT smbolo] FOREIGN KEY (nombre_columna, ...)
REFERENCES nombre_tabla (nombre_columna, ...)
[ON DELETE {CASCADE | SET NULL | NO ACTION
| RESTRICT}]
[ON UPDATE {CASCADE | SET NULL | NO ACTION
| RESTRICT}]
Las columnas correspondientes en la clave fornea y en la clave referenciada deben tener tipos de
datos similares para que puedan ser comparadas sin la necesidad de hacer una conversin de
tipos. El tamao y el signo de los tipos enteros debe ser el mismo. En las columnas de tipo
caracter, el tamao no tiene que ser el mismo necesariamente.
Si MySQL da un error cuyo nmero es el 1005 al momento de ejecutar una sentencia CREATE
TABLE, y el mensaje de error se refiere al nmero 150, la creacin de la tabla fall porque la
restriccin de la clave fornea no se hizo de la manera adecuada. De la misma manera, si falla una
sentencia ALTER TABLE y se hace referencia al error nmero 150, esto significa que la definicin
de la restriccin de la clave fornea no se hizo adecuadamente. A partir de la versin 4.0.13 de
MySQL, se puede usar la sentencia SHOW INNODB STATUS para ver una explicacin detallada
del ltimo error que se gener en relacin a la definicin de una clave fornea.
Si en una tabla, un registro contiene una clave fornea con un valor NULO, significa que no existe
niguna relacin con otra tabla.
A partir de la versin 3.23.50, se pueden agregar restricciones de clave fornea a una tabla con el
uso de la sentencia ALTER TABLE. La sintaxis es:
ALTER TABLE nombre_tabla ADD [CONSTRAINT smbolo] FOREIGN KEY(...)
REFERENCES otra_tabla(...) [acciones_ON_DELETE][acciones_ON_UPDATE]
Por ejemplo, la creacin de la clave fornea en la tabla venta que se mostr anteriormente pudo
haberse hecho de la siguiente manera con el uso de una sentencia ALTER TABLE:
CREATE TABLE venta
(
id_factura INT NOT NULL,
id_cliente INT NOT NULL,
cantidad INT,
PRIMARY KEY(id_factura),
INDEX (id_cliente)
) TYPE = INNODB;

ALTER TABLE venta ADD FOREIGN KEY(id_cliente) REFERENCES cliente(id_cliente);
En las versiones 3.23.50 y menores no deben usarse las sentencias ALTER TABLE o CREATE
INDEX en tablas que ya tienen definidas restricciones de claves forneas o bien, que son
referenciadas en restricciones de claves forneas: cualquier sentencia ALTER TABLE elimina
todas las restricciones de claves forneas definidas para la tabla.
No debe usarse una sentencia ALTER TABLE en una tabla que est siendo referenciada, si se
quiere modificar el esquema de la tabla, se recomienda eliminar la tabla y volverla a crear con el
nuevo esquema. Cuando MySQL hace un ALTER TABLE, puede que use de manera interna un
RENAME TABLE, y por lo tanto, se confundan las restricciones de clave fornea que se refieren a
la tabla. Esta restriccin aplica tambin en el caso de la sentencia CREATE INDEX, ya que MySQL
la procesa como un ALTER TABLE.
Cuando se ejecute un script para cargar registros en una base de datos, es recomendable agregar
las restricciones de claves forneas va un ALTER TABLE. De esta manera no se tiene el problema
de cargar los registros en las tablas de acuerdo a un orden lgico (las tablas referenciadas
deberan ir primero).
Insercin de registros con claves forneas
La integridad referencial se puede comprometer bsicamente en tres situaciones: cuando se est
insertando un nuevo registro, cuando se est eliminando un registro, y cuando se est actualizando
un registro. La restriccin de clave fornea que hemos definido se asegura que cuando un nuevo
registro sea creado en la tabla venta, ste debe tener su correspondiente registro en la tabla
cliente.
Una vez que hemos creado las tablas, vamos a insertar algunos datos que nos sirvan para
demostrar algunos conceptos importantes:
mysql> INSERT INTO cliente VALUES(1,'Juan Penas');
Query OK, 1 row affected (0.05 sec)

mysql> INSERT INTO cliente VALUES(2,'Pepe el toro');
Query OK, 1 row affected (0.05 sec)

mysql> INSERT INTO venta VALUES(1,1,23);
Query OK, 1 row affected (0.03 sec)

mysql> INSERT INTO venta VALUES(3,2,81);
Query OK, 1 row affected (0.03 sec)
En este momento no hay ningn problema, sin embargo, vamos a ver que sucede cuando
intentamos insertar un registro en la tabla venta que se refiera a un cliente no existente cuyo
id_cliente es 3:
mysql> INSERT INTO venta VALUES(2,3,39);
ERROR 1216: Cannot add or update a child row: a foreign key constraint fails
El hecho es que MySQL no nos permite insertar este registro, ya que el cliente cuyo id_cliente es 3
no existe. La restriccin de clave fornea asegura que nuestros datos mantienen su integridad. Sin
embargo, qu sucede cuando eliminamos algn registro?. Vamos a agregar un nuevo cliente, y
un nuevo registro en la tabla venta, posteriormente eliminaremos el registro de nuestro tercer
cliente:
mysql> INSERT INTO cliente VALUES(3,'Pepe pecas');
Query OK, 1 row affected (0.05 sec)

mysql> INSERT INTO venta VALUES(2,3,39);
Query OK, 1 row affected (0.05 sec)

mysql> DELETE FROM cliente WHERE id_cliente=3;
ERROR 1217: Cannot delete or update a parent row: a foreign key constraint fails
Debido a nuestra restriccin de clave fornea, MySQL no permite que eliminemos el registro de
cliente cuyo id_cliente es 3, ya que se hace referencia a ste en la tabla venta. De nuevo, se
mantiene la integridad de nuestros datos. Sin embargo existe una forma en la cul podramos
hacer que la sentencia DELETE se ejecute de cualquier manera, y la veremos brevemente, pero
primero necesitamos saber como eliminar (quitar) una clave fornea.
Eliminacin de una clave fornea
No podemos slo eliminar una restriccin de clave fornea como si fuera un ndice ordinario.
Veamos que sucede cuando lo intentamos.
mysql> ALTER TABLE venta DROP FOREIGN KEY;
ERROR 1005: Can't create table '.test#sql-228_4.frm' (errno: 150)
Para eliminar la clave fornea se tiene que especificar el ID que ha sido generado y asignado
internamente por MySQL a la clave fornea. En este caso, se puede usar la sentencia SHOW
CREATE TABLE para determinar dicho ID.
mysql> SHOW CREATE TABLE venta;
+--------+-----------------------------------------------------+
| Table | Create Table |
+--------+-----------------------------------------------------+
| venta | CREATE TABLE 'venta' ( |
| | 'id_factura' int(11) NOT NULL default '0', |
| | 'id_cliente' int(11) NOT NULL default '0', |
| | 'cantidad' int(11) default NULL, |
| | PRIMARY KEY ('id_factura'), |
| | KEY 'id_cliente' ('id_cliente'), |
| | CONSTRAINT '0_22' FOREIGN KEY ('id_cliente') |
| | REFERENCES 'cliente' ('id_cliente') ) TYPE=InnoDB |
+-------+------------------------------------------------------+
1 row in set (0.00 sec)
En nuestro ejemplo, la restriccin tiene el ID 0_22 (es muy probable que este valor sea diferente en
cada caso).
mysql> ALTER TABLE venta DROP FOREIGN KEY 0_22;
Query OK, 3 rows affected (0.23 sec)
Records: 3 Duplicates: 0 Warnings: 0

Eliminacin de registros con claves forneas
Una de las principales bondades de las claves forneas es que permiten eliminar y actualizar
registros en cascada.
Con las restriccciones de clave fornea podemos eliminar un registro de la tabla cliente y a la vez
eliminar un registro de la tabla venta usando slo una sentencia DELETE. Esto es llamado
eliminacin en cascada, en donde todos los registros relacionados son eliminados de acuerdo a las
relaciones de clave fornea. Una alternativa es no eliminar los registros relacionados, y poner el
valor de la clave fornea a NULL (asumiendo que el campo puede tener un valor nulo). En nuestro
caso, no podemos poner el valor de nuestra clave fornea id_cliente en la tabla venta, ya que se
ha definido como NOT NULL. Las opciones estndar cuando se elimina una registro con clave
fornea son:
ON DELETE RESTRICT
ON DELETE NO ACTION
ON DELETE SET DEFAULT
ON DELETE CASCADE
ON DELETE SET NULL
ON DELETE RESTRICT es la accin predeterminada, y no permite una eliminacin si existe un
registro asociado, como se mostr en el ejemplo anterior. ON DELETE NO ACTION hace lo
mismo.
ON DELETE SET DEFAULT actualmente no funciona en MySQL - se supone que pone el valor de
la clave fornea al valor por omisin (DEFAULT) que se defini al momento de crear la tabla.
Si se especifica ON DELETE CASCADE, y una fila en la tabla padre es eliminada, entonces se
eliminarn las filas de la tabla hijo cuya clave fornea sea igual al valor de la clave referenciada en
la tabla padre. Esta accin siempre ha estado disponible en MySQL.
Si se especifica ON DELETE SET NULL, las filas en la tabla hijo son actualizadas
automticamente poniendo en las columnas de la clave fornea el valor NULL. Si se especifica una
accin SET NULL, debemos asegurarnos de no declarar las columnas en la tabla como NOT
NULL.
A continuacin se muestra un ejemplo de eliminacin en cascada:
mysql> ALTER TABLE venta ADD FOREIGN KEY(id_cliente)
-> REFERENCES cliente(id_cliente) ON DELETE CASCADE;
Query OK, 3 rows affected (0.23 sec)
Records: 3 Duplicates: 0 Warnings: 0
Vamos a ver como estn nuestros registros antes de ejecutar la sentencia DELETE:
mysql> SELECT * FROM cliente;
+------------+--------------+
| id_cliente | nombre |
+------------+--------------+
| 1 | Juan Penas |
| 2 | Pepe el toro |
| 3 | Pepe pecas |
+------------+--------------+
3 rows in set (0.00 sec)


mysql> SELECT * FROM venta;


+------------+------------+----------+
| id_factura | id_cliente | cantidad |
+------------+------------+----------+
| 1 | 1 | 23 |
| 2 | 3 | 39 |
| 3 | 2 | 81 |
+------------+------------+----------+
3 rows in set (0.00 sec)
Ahora eliminaremos a Pepe Pecas de la base de datos:
mysql> DELETE FROM cliente WHERE id_cliente=3;
Query OK, 1 row affected (0.05 sec)

mysql> SELECT * FROM venta;
+------------+------------+----------+
| id_factura | id_cliente | cantidad |
+------------+------------+----------+
| 1 | 1 | 23 |
| 3 | 2 | 81 |
+------------+------------+----------+
2 rows in set (0.00 sec)


mysql> SELECT * FROM cliente;


+------------+--------------+
| id_cliente | nombre |<


Leer ms: http://ingsystemas.webnode.es/bases-de-datos/llaves-primarias-y-foraneas/
Crea tu propia web gratis: http://www.webnode.es



http://ict.udlap.mx/people/carlos/is341/bases03.html
http://www.slideshare.net/HugoSanchez34/modelo-relacional-16764703
http://www.estructurayprogramacion.com/materias/fundamentos-de-base-de-datos/

Potrebbero piacerti anche