Integridad de datos

Es muy importante impedir situaciones que hagan que los datos no sean accesibles, o que existan datos almacenados que no se refieran a objetos o entidades existentes, etc. El modelo relacional también provee mecanismos para mantener la integridad. Podemos dividir estos mecanismos en dos categorías:

  • Restricciones estáticas, que se refieren a los estados válidos de datos almacenados.
  • Restricciones dinámicas, que definen las acciones a realizar para evitar ciertos efectos secundarios no deseados cuando se realizan operaciones de modificación o borrado de datos.

Restricciones sobre claves primarias

En cuanto a las restricciones estáticas, las más importantes son las que afectan a las claves primarias.

Ninguna de las partes que componen una clave primaria puede ser NULL.

Que parte de una clave primaria sea NULL indicaría que, o bien esa parte no es algo absolutamente necesario para definir la entidad, con lo cual no debería formar parte de la clave primaria, o bien no sabemos a qué objeto concreto nos estamos refiriendo, lo que implica que estamos tratando con un grupo de entidades. Esto va en contra de la norma que dice que cada tupla contiene datos sólo de una entidad.

Las modificaciones de claves primarias deben estar muy bien controladas.

Dado que una clave primaria identifica de forma unívoca a una tupla en una relación, parece poco lógico que exista necesidad de modificarla, ya que eso implicaría que no estamos definiendo la misma entidad.

Además, hay que tener en cuenta que las claves primarias se usan frecuentemente para establecer interrelaciones, lo cual implica que sus valores se usan en otras relaciones. Si se modifica un valor de una clave primaria hay que ser muy cuidadoso con el efecto que esto puede tener en todas las relaciones en las que se guarden esos valores.

Existen varias maneras de limitar la modificación de claves primarias. Codd apuntó tres posibilidades:

  • Que sólo un número limitado de usuarios puedan modificar los valores de claves primarias. Estos usuarios deben ser conscientes de las repercusiones de tales cambios, y deben actuar de modo que se mantenga la integridad.
  • La prohibición absoluta de modificar los valores de claves primarias. Modificarlas sigue siendo posible, pero mediante un mecanismo indirecto. Primero hay que eliminar las tuplas cuyas claves se quieren modificar y a continuación darlas de alta con el nuevo valor de clave primaria.
  • La creación de un comando distinto para modificar atributos que son claves primarias o partes de ellas, del que se usa para modificar el resto de los atributos.

Cada SGBD puede implementar alguno o varios de estos métodos.

Integridad referencial

La integridad referencial se refiere a las claves foráneas. Recordemos que una clave foránea es un atributo de una relación, cuyos valores se corresponden con los de una clave primaria en otra o en la misma relación. Este mecanismo se usa para establecer interrelaciones.

La integridad referencial consiste en que si un atributo o conjunto de atributos se define como una clave foránea, sus valores deben existir en la tabla en que ese atribito es clave principal.

Las situaciones donde puede violarse la integridad referencial es en el borrado de tuplas o en la modificación de claves principales. Si se elimina una tupla cuya clave primaria se usa como clave foránea en otra relación, las tuplas con esos valores de clave foránea contendrán valores sin referenciar.

Existen varias formas de asegurarse de que se conserva la integridad referencial:

  • Restringir operaciones: borrar o modificar tuplas cuya clave primaria es clave foránea en otras tuplas, sólo estará permitido si no existe ninguna tupla con ese valor de clave en ninguna otra relación.
    Es decir, si el valor de una clave primaria en una tupla es "clave1", sólo podremos eliminar esa tupla si el valor "clave1" no se usa en ninguna otra tupla, de la misma relación o de otra, como valor de clave foránea.
  • Transmisión en cascada: borrar o modificar tuplas cuya clave primaria es clave foránea en otras implica borrar o modificar las tuplas con los mismos valores de clave foránea.
    Si en el caso anterior, modificamos el valor de clave primaria "clave1" por "clave2", todas las apariciones del valor "clave1" en donde sea clave foránea deben ser sustituidos por "clave2".
  • Poner a nulo: cuando se elimine una tupla cuyo valor de clave primaria aparece en otras relaciones como clave foránea, se asigna el valor NULL a dichas claves foráneas.
    De nuevo, siguiendo el ejemplo anterior, si eliminamos la tupla con el valor de clave primaria "clave1", en todas las tuplas donde aparezca ese valor como clave foránea se sustituirá por NULL.

Veremos con mucho más detalle como se implementan estos mecanismos en MySQL al estudiar el lenguaje SQL.

Propagación de claves

Se trata de un concepto que se aplica a interrelaciones N:1 ó 1:1, que nos ahorra la creación de una relación. Supongamos las siguientes relaciones, resultado del paso del ejemplo 2 del modelo E-R al modelo relacional:

Libro(ClaveLibro, Título, Idioma, Formato, Categoría)
Editado_por(ClaveLibro, ClaveEditorial)
Editorial(ClaveEditorial, Nombre, Dirección, Teléfono)

Cada libro sólo puede estar editado por una editorial, la interrelación es N:1. En este caso podemos prescindir de la relación Editado_por añadiendo un atributo a la relación Libro, que sea la clave primaria de la editorial:

Libro(ClaveLibro, Título, Idioma, Formato, Categoría, ClaveEditorial)
Editorial(ClaveEditorial, Nombre, Dirección, Teléfono)

A esto se le denomina propagación de la clave de la entidad Editorial a la entidad Libro.

Por supuesto, este mecanismo no es válido para interrelaciones de N:M, como por ejemplo, la que existe entre Libro y Autor.

Ejemplo 1

Para ilustrar el paso del modelo E-R al modelo relacional, usaremos los mismos ejemplos que en el capítulo anterior, y convertiremos los diagramas E-R a tablas.

Empecemos con el primer ejemplo:

2º diagrama meteorológico

Sólo necesitamos dos tablas para hacer la conversión:

Estación(Identificador, Latitud, Longitud, Altitud)
Muestra(IdentificadorEstacion, Fecha, Temperatura mínima, Temperatura máxima,
  Precipitaciones, Humedad mínima, Humedad máxima, Velocidad del viento mínima,
  Velocidad del viento máxima)

Este ejemplo es muy simple, la conversión es directa. Se puede observar cómo hemos introducido un atributo en la relación Muestra que es el identificador de estación. Este atributo se comporta como una clave foránea.

Ejemplo 2

2º diagrama de biblioteca

Este ejemplo es más complicado, de modo que iremos por fases. Para empezar, convertiremos los conjuntos de entidades en relaciones:

Libro(ClaveLibro, Título, Idioma, Formato)
Tema(ClaveTema, Nombre)
Autor(ClaveAutor, Nombre)
Editorial(ClaveEditorial, Nombre, Dirección, Teléfono)
Ejemplar(ClaveEjemplar, ClaveLibro, NúmeroOrden, Edición, Ubicación, Categoría)
Socio(ClaveSocio, Nombre, Dirección, Teléfono, Categoría)

Recordemos que Préstamo es una entidad compuesta:

Préstamo(ClaveSocio, ClaveEjemplar, Fecha_préstamo, Fecha_devolución, Notas)

La entidad Ejemplar es subordinada de Libro, es decir, que su clave principal se podría construir a partir de la clave principal de Libro y el atributo NúmeroOrden. Sin embargo crearemos una clave específica para ello.

Ahora veamos la conversión de las interrelaciones:

Trata_sobre(ClaveLibro, ClaveTema)
Escrito_por(ClaveLibro, ClaveAutor)
Editado_por(ClaveLibro, ClaveEditorial)

Ya vimos que podemos aplicar la propagación de claves entre conjuntos de entidades que mantengan una interrelación N:1 ó 1:1. En este caso, la interrelación entre Libro y Editorial cumple esa condición, de modo que podemos eliminar una interrelación y propagar la clave de Editorial a la entidad Libro.

El esquema final queda así:

Libro(ClaveLibro, Título, Idioma, Formato, ClaveEditorial)
Tema(ClaveTema, Nombre)
Autor(ClaveAutor, Nombre)
Editorial(ClaveEditorial, Nombre, Dirección, Teléfono)
Ejemplar(ClaveEjemplar, ClaveLibro, NúmeroOrden, Edición, Ubicación, Categoría)
Socio(ClaveSocio, Nombre, Dirección, Teléfono, Categoría)
Préstamo(ClaveSocio, ClaveEjemplar, Fecha_préstamo, Fecha_devolución, Notas)
Trata_sobre(ClaveLibro, ClaveTema)
Escrito_por(ClaveLibro, ClaveAutor)