0 valutazioniIl 0% ha trovato utile questo documento (0 voti)
126 visualizzazioni21 pagine
El documento explica los conceptos de claves primarias, claves foráneas e índices en bases de datos. Indica que las claves primarias identifican registros de forma única, mientras que las claves foráneas hacen referencia a claves primarias en otras tablas para establecer relaciones. También describe cómo generar números secuenciales automáticos para usar como claves primarias e implementar índices.
El documento explica los conceptos de claves primarias, claves foráneas e índices en bases de datos. Indica que las claves primarias identifican registros de forma única, mientras que las claves foráneas hacen referencia a claves primarias en otras tablas para establecer relaciones. También describe cómo generar números secuenciales automáticos para usar como claves primarias e implementar índices.
El documento explica los conceptos de claves primarias, claves foráneas e índices en bases de datos. Indica que las claves primarias identifican registros de forma única, mientras que las claves foráneas hacen referencia a claves primarias en otras tablas para establecer relaciones. También describe cómo generar números secuenciales automáticos para usar como claves primarias e implementar í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(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> 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)