El módulo 4 terminó con una promesa: someter el esquema de BiblioRed a un examen formal. Hasta ahora hemos diseñado por comprensión del dominio, guiados por dos principios intuitivos —"una cosa, un sitio" y "un hecho, una fila"— que funcionan sorprendentemente bien pero que no se pueden demostrar. Cuando dos personas discrepan sobre si una tabla está bien diseñada, la intuición no arbitra. La normalización sí: es un cuerpo de teoría, publicado por Edgar Codd entre 1970 y 1974 y ampliado después, que convierte esos principios en definiciones con las que se puede razonar y, llegado el caso, discutir con argumentos.

Esta lección es la preparación. No define todavía ninguna forma normal: construye el vocabulario y las herramientas que hacen falta para entenderlas. Concretamente, responde a tres preguntas. Primera: ¿qué daño hace exactamente la redundancia, más allá de "ocupa espacio"? Segunda: ¿cómo se escribe formalmente una regla del tipo "el ISBN determina el título"? Tercera: ¿cómo se calcula, con un procedimiento mecánico y no a ojo, cuál es la clave de una tabla? Sin estas tres cosas, las formas normales de la lección siguiente son fórmulas memorizadas; con ellas, son consecuencias evidentes.

Trabajaremos casi todo el tiempo sobre un material que ya conocemos: la vieja hoja de cálculo de préstamos de BiblioRed, la que diagnosticamos en la lección 01-01 y que desde entonces hemos usado como ejemplo de todo lo que no hay que hacer. Ha llegado el momento de desmontarla formalmente.

Contenido

  1. Qué es normalizar y qué no es
  2. Por qué la redundancia es el problema (y no el espacio en disco)
  3. La hoja de préstamos como relación única: prestamos_hoja
  4. Las tres anomalías, demostradas una a una
  5. Dependencias funcionales: definición y notación
  6. De dónde salen las dependencias: reglas de negocio, no datos de muestra
  7. Tipos de dependencia: total, parcial y transitiva
  8. Dependencias triviales
  9. El grafo de dependencias de prestamos_hoja
  10. Los axiomas de Armstrong
  11. Las reglas derivadas: unión, descomposición, pseudotransitividad
  12. El cierre de un conjunto de atributos (X⁺)
  13. Encontrar las claves candidatas con el cierre
  14. Atributos primos y no primos
  15. Qué viene ahora: las formas normales

  1. Qué es normalizar y qué no es

Normalizar es reorganizar los atributos de una base de datos en tablas de forma que cada hecho quede almacenado exactamente una vez, y hacerlo siguiendo un procedimiento que se puede justificar.

Esa definición tiene dos mitades y las dos importan. La primera mitad ("cada hecho una vez") es el objetivo. La segunda ("un procedimiento justificable") es lo que distingue la normalización de la intuición del módulo 4. Cuando terminemos el módulo, podrás decir de una tabla no solo "esto está mal" sino "esto viola la segunda forma normal porque ejemplar_cod → isbn es una dependencia parcial de la clave (ejemplar_cod, fecha_prestamo)", que es una frase que se puede verificar o refutar.

Vale la pena ser explícitos sobre lo que no es normalizar, porque las tres confusiones siguientes son muy frecuentes:

No es "partir tablas por partirlas". Hay quien cree que normalizar significa tener muchas tablas pequeñas y que cuantas más, mejor. Es falso. Una descomposición solo está justificada si elimina una dependencia problemática concreta. Partir socios en socios_datos_basicos y socios_datos_contacto sin ninguna dependencia que lo motive no normaliza nada: añade un JOIN a cada consulta y no elimina ninguna redundancia. Si no puedes nombrar la dependencia que estás eliminando, no estás normalizando.

No es un fin en sí mismo. El objetivo del sistema de BiblioRed es prestar libros, no exhibir un esquema en quinta forma normal. La normalización es un medio para que los datos no se contradigan. Cuando deja de servir a ese fin —cuando el coste de los JOIN supera el beneficio de la coherencia— se hace lo contrario a propósito, y eso tiene nombre y método: es la lección 05-04.

No es limpieza de datos. Este punto es sutil y conviene fijarlo desde el principio. En la hoja de BiblioRed conviven "Ken Follet" y "Ken Follett", y un ISBN al que le falta un dígito. Normalizar el esquema no corrige esos errores: si metes datos sucios en un esquema perfectamente normalizado, obtienes datos sucios bien organizados. Lo que hace la normalización es eliminar la posibilidad de que el error vuelva a producirse: cuando el nombre del autor está escrito una sola vez en autores, no hay manera física de que existan dos grafías distintas. La limpieza del histórico es un trabajo aparte que se hace durante la migración, y lo veremos en la lección 05-03.

Los dos objetivos, ordenados

Objetivo Qué significa Cómo se comprueba
Eliminar la redundancia que produce inconsistencia Que ningún hecho esté almacenado en dos sitios donde puedan discrepar Buscando dependencias funcionales que no salgan de una clave
Preservar la información Que después de descomponer se pueda reconstruir exactamente lo que había Con las propiedades de descomposición sin pérdida y conservación de dependencias (05-03)

El segundo objetivo es tan importante como el primero y se olvida más. Una descomposición que elimina toda la redundancia pero pierde información es un desastre, no un logro.

  1. Por qué la redundancia es el problema (y no el espacio en disco)

Es habitual justificar la normalización diciendo que "ahorra espacio". Es cierto que lo ahorra, y en 1970, con discos de megabytes carísimos, era un argumento de peso. Hoy no lo es: el disco vale casi nada y repetir el nombre de una sucursal cuarenta mil veces cuesta unos pocos megabytes que a nadie preocupan.

El verdadero problema de la redundancia es que crea la posibilidad física de la contradicción.

Piensa en lo que significa que un dato esté escrito dos veces. Significa que existen dos lugares en el disco que afirman algo sobre el mundo, y que el sistema no tiene ninguna garantía de que afirmen lo mismo. Mientras nadie los toque, coinciden. En el momento en que una operación actualiza uno y no el otro —porque el programa tenía un error, porque la conexión se cortó a medias, porque el operario del mostrador corrigió lo que veía en pantalla sin saber que había más copias— la base de datos pasa a contener dos verdades incompatibles. Y no hay forma automática de saber cuál es la buena.

En la hoja de BiblioRed esto ya ocurrió, y por eso es un ejemplo tan útil:

  • La sucursal aparece como Norte en tres filas y como norte en una. Un GROUP BY sucursal devuelve dos sucursales donde hay una.
  • El autor aparece como Ken Follet en una fila y Ken Follett en otra. Buscar los préstamos de Follett devuelve la mitad.
  • El correo de Marta Alsina aparece como [email protected] en dos filas y [email protected] en una. ¿Cuál es el bueno? Nadie lo sabe sin llamarla por teléfono.

Ninguno de estos tres problemas es un problema de espacio. Los tres son el mismo problema: el dato está en varios sitios, alguien tocó uno, y ahora la base de datos miente.

Hay una formulación que conviene memorizar: la redundancia no causa la inconsistencia, la hace posible; y todo lo que es posible, con suficientes filas y suficiente tiempo, ocurre. Una base de datos con cuarenta mil préstamos y ocho años de historia acumula una cantidad de contradicciones proporcional a la cantidad de redundancia que le permitas.

  1. La hoja de préstamos como relación única: prestamos_hoja

Para trabajar formalmente necesitamos que la hoja de cálculo sea una tabla con nombres de columna razonables. Vamos a llamarla prestamos_hoja y le damos esta estructura, que es la del fichero original con las columnas renombradas y sin nada añadido:

-- La hoja de cálculo, tal cual, convertida en tabla.
-- No es un diseño: es el punto de partida que vamos a demoler.
CREATE TABLE prestamos_hoja (
    ejemplar_cod     VARCHAR(10)  NOT NULL,   -- 'EJ-3081', la etiqueta del lomo
    fecha_prestamo   DATE         NOT NULL,
    fecha_devolucion DATE,                    -- NULL = préstamo abierto
    socio_email      VARCHAR(120) NOT NULL,
    socio_nombre     VARCHAR(120) NOT NULL,
    socio_telefono   VARCHAR(20),
    isbn             VARCHAR(13)  NOT NULL,
    titulo           VARCHAR(200) NOT NULL,
    autor            VARCHAR(120) NOT NULL,
    autor_nac        VARCHAR(40),             -- nacionalidad del autor
    sucursal_nombre  VARCHAR(60)  NOT NULL,   -- sucursal donde vive el ejemplar
    sucursal_ciudad  VARCHAR(60)  NOT NULL,
    sucursal_cp      VARCHAR(5)   NOT NULL,
    CONSTRAINT pk_prestamos_hoja PRIMARY KEY (ejemplar_cod, fecha_prestamo)
);

Y estos son los datos, ya con las grafías unificadas para poder razonar sobre la estructura sin que los errores tipográficos nos distraigan (los recuperaremos en 05-03, donde hay que limpiarlos de verdad):

ejemplar_cod fecha_prestamo fecha_devolucion socio_email socio_nombre socio_telefono isbn titulo autor autor_nac sucursal_nombre sucursal_ciudad sucursal_cp
EJ-3081 2026-03-02 2026-03-16 [email protected] Marta Alsina 600111222 9788401339097 El mapa del tiempo Félix J. Palma española Norte Vallmar 08110
EJ-3081 2026-04-05 (NULL) [email protected] Marta Alsina 600111222 9788401339097 El mapa del tiempo Félix J. Palma española Norte Vallmar 08110
EJ-3090 2026-04-07 2026-04-21 [email protected] Iván Pereda 600333444 9788401337208 Los pilares de la Tierra Ken Follett británica Norte Vallmar 08110
EJ-3082 2026-04-09 (NULL) [email protected] Marta Alsina 600111222 9788401339097 El mapa del tiempo Félix J. Palma española Norte Vallmar 08110
EJ-3095 2026-04-10 (NULL) [email protected] Nuria Bastos 600555666 9788401337208 Los pilares de la Tierra Ken Follett británica Sur Vallmar 08130

Cinco filas. Cuenta cuántas veces aparece la cadena Félix J. Palma: tres. Cuántas veces Vallmar: cinco. Cuántas veces el teléfono de Marta: tres. Con cinco filas es una curiosidad; con los 84.000 préstamos que BiblioRed lleva registrados desde 2018, es un problema estructural.

Una aclaración sobre la clave primaria antes de seguir. He puesto (ejemplar_cod, fecha_prestamo) porque la regla de negocio de BiblioRed dice que un ejemplar físico no puede estar prestado dos veces el mismo día: solo hay una copia, y si se la llevó alguien, no se la puede llevar otro hasta que vuelva. En la sección 13 comprobaremos formalmente que esa pareja es efectivamente una clave, en lugar de darlo por bueno.

  1. Las tres anomalías, demostradas una a una

La lección 04-01 nombró las tres anomalías en una tabla de tres líneas y prometió explicarlas aquí. Vamos a ello, y esta vez con SQL que las provoca de verdad.

Una anomalía es un comportamiento indeseable que aparece al insertar, modificar o borrar filas de una tabla mal diseñada. No es un error del programador ni un fallo del SGBD: es una consecuencia inevitable de la estructura de la tabla. Con prestamos_hoja no puedes evitarlas por mucho cuidado que pongas, porque están en el diseño.

4.1 Anomalía de inserción

No se puede registrar un hecho porque falta otro hecho sin relación con él.

BiblioRed acaba de incorporar a su catálogo de autores a Ken Follett con su nacionalidad correcta, y quiere registrar también que existe una sucursal nueva, Este, en el código postal 08140. Intentémoslo:

-- Quiero registrar que Ken Follett es británico. Nada más.
INSERT INTO prestamos_hoja (autor, autor_nac)
VALUES ('Ken Follett', 'británica');
ERROR:  el valor null para la columna «ejemplar_cod» viola la restricción no nulo

No se puede. Para guardar un dato sobre un autor hay que inventarse un préstamo: un ejemplar, una fecha, un socio, un ISBN. La información sobre autores no tiene dónde vivir si no es colgada de un préstamo.

Lo mismo con la sucursal nueva:

-- La sucursal Este abre el mes que viene y todavía no ha prestado nada.
INSERT INTO prestamos_hoja (sucursal_nombre, sucursal_ciudad, sucursal_cp)
VALUES ('Este', 'Vallmar', '08140');
ERROR:  el valor null para la columna «ejemplar_cod» viola la restricción no nulo

La única salida sería insertar una fila con valores inventados o NULL en todo lo demás —una "fila fantasma"— y eso envenena todas las consultas: los recuentos de préstamos salen mal, los promedios de días salen mal, y alguien acabará preguntando por qué hay un préstamo sin socio.

Traducción del problema: la tabla mezcla hechos sobre préstamos con hechos sobre autores y sucursales, y solo tiene clave para lo primero. Los hechos de las otras entidades quedan atrapados.

4.2 Anomalía de actualización (o de modificación)

Cambiar un hecho obliga a modificar muchas filas; si una se escapa, la base de datos se contradice.

El ayuntamiento de Vallmar rebautiza la sucursal Norte como "Vallmar Nord". En un esquema normalizado esto es un UPDATE de una sola fila. Aquí:

UPDATE prestamos_hoja
SET sucursal_nombre = 'Vallmar Nord'
WHERE sucursal_nombre = 'Norte';
UPDATE 4

Cuatro filas en la muestra; unas 31.000 en el fichero real. Y ese UPDATE funcionó porque todas las filas decían exactamente Norte. En el fichero original una decía norte en minúscula, y por tanto no entró en el WHERE:

-- Después del UPDATE anterior, ¿qué sucursales existen?
SELECT sucursal_nombre, COUNT(*) AS filas
FROM prestamos_hoja
GROUP BY sucursal_nombre;
 sucursal_nombre | filas
-----------------+-------
 Vallmar Nord    |     3
 norte           |     1
 Sur             |     1

Ahí está la anomalía en su forma más pura: una sucursal que ahora existe con dos nombres distintos porque una fila se quedó fuera de la actualización. Es exactamente el defecto número 7 del diagnóstico de 01-01, y ahora sabemos que no fue mala suerte ni descuido del operario: es la consecuencia matemática de tener el nombre de la sucursal repetido en 31.000 filas.

Lo mismo pasa con el teléfono de Marta Alsina. Si cambia de número, hay que tocar las tres filas donde aparece; si solo se actualizan dos, BiblioRed tiene dos teléfonos para la misma persona y ninguna forma de saber cuál marcar.

Traducción del problema: el nombre de la sucursal es un hecho sobre la sucursal, no sobre el préstamo, pero está almacenado una vez por préstamo.

4.3 Anomalía de borrado

Borrar una fila destruye información que no tenía nada que ver.

Iván Pereda pide que se borre su historial de préstamos, y BiblioRed está obligada a atenderle. Su préstamo de "Los pilares de la Tierra" es, digamos, el único que queda de ese ejemplar:

DELETE FROM prestamos_hoja
WHERE socio_email = '[email protected]';
DELETE 1

Al borrar esa fila hemos perdido, sin quererlo:

  • Que existe un ejemplar llamado EJ-3090.
  • Que el ISBN 9788401337208 corresponde a "Los pilares de la Tierra".
  • Que su autor es Ken Follett.
  • Que Ken Follett es británico.

Si esa fila hubiera sido la última con Follett en toda la tabla, Ken Follett habría dejado de existir en la base de datos de BiblioRed. Un dato de catálogo, permanente, borrado por una operación sobre un préstamo. Ninguna auditoría lo detectaría: la fila se borró correctamente, la operación tuvo éxito, y sin embargo se perdió información.

-- ¿Sigue BiblioRed sabiendo quién es Ken Follett?
SELECT DISTINCT autor, autor_nac
FROM prestamos_hoja
WHERE autor = 'Ken Follett';
 autor | autor_nac
-------+-----------
(0 filas)

Traducción del problema: la existencia del autor está condicionada a la existencia de al menos un préstamo suyo, cuando en el mundo real son cosas independientes.

Las tres, en una tabla

Anomalía Operación Qué falla Ejemplo en prestamos_hoja
De inserción INSERT No se puede guardar un hecho sin inventar otro No se puede registrar la sucursal Este hasta que preste algo
De actualización UPDATE Un cambio afecta a N filas; si falla una, hay contradicción "Norte" pasa a "Vallmar Nord" en 3 filas y sigue siendo "norte" en 1
De borrado DELETE Se pierde información ajena a la fila borrada Borrar el último préstamo de Follett borra a Follett

Las tres tienen la misma causa: la tabla guarda hechos sobre varias entidades distintas (préstamo, socio, libro, autor, sucursal) en una sola fila, y solo una de esas entidades manda sobre la clave. Todo lo demás está de prestado.

Y aquí está el gran salto conceptual de esta lección: esa causa se puede escribir con precisión. La herramienta para hacerlo son las dependencias funcionales.

  1. Dependencias funcionales: definición y notación

Una dependencia funcional es una regla que dice que, conocido el valor de unos atributos, el valor de otros queda determinado sin ambigüedad.

Definición. Sean X e Y dos conjuntos de atributos de una relación R. Decimos que X determina funcionalmente a Y, y lo escribimos X → Y, si para cualquier par de filas de R que coincidan en todos los atributos de X, necesariamente coinciden también en todos los atributos de Y.

Vamos con el vocabulario, porque cada símbolo cuenta y aquí no damos por supuesta ninguna base matemática:

  • Atributo: una columna. isbn es un atributo.
  • Conjunto de atributos: un grupo de columnas, que se escribe entre llaves: {ejemplar_cod, fecha_prestamo}. Cuando el conjunto tiene un solo elemento, las llaves se suelen omitir: isbn en lugar de {isbn}.
  • La flecha : se lee "determina". isbn → titulo se lee "el ISBN determina el título". No es una asignación, ni una implicación lógica, ni una flecha de un diagrama: es un símbolo específico de esta teoría.
  • El lado izquierdo (X) se llama determinante. El derecho (Y), determinado o dependiente.
  • La yuxtaposición significa unión: XY es una forma abreviada de escribir "el conjunto formado por todos los atributos de X más todos los de Y". La operación se llama unión y su símbolo formal es , así que XY y X ∪ Y son lo mismo. Verás las dos notaciones en la bibliografía.

Cómo se lee una dependencia en lenguaje llano

isbn → titulo dice: "si dos filas tienen el mismo ISBN, tienen forzosamente el mismo título". O, dicho al revés y de forma más útil: "no puede existir un ISBN con dos títulos distintos". Esta segunda formulación —como una prohibición— suele ser la más fácil de validar con la persona que conoce el negocio.

Fíjate en que la dependencia no dice nada en sentido contrario. isbn → titulo no implica titulo → isbn: dos ediciones distintas de "El mapa del tiempo" pueden compartir título y tener ISBN diferentes. Las dependencias tienen dirección, y confundirla es el error número uno de quien empieza.

Dependencias con determinante compuesto

El lado izquierdo puede tener varios atributos:

{ejemplar_cod, fecha_prestamo} → fecha_devolucion

Se lee: "conocidos el ejemplar y la fecha en que se prestó, la fecha de devolución queda determinada". Y tiene sentido: ese par identifica un préstamo concreto, y un préstamo concreto se devolvió un día concreto (o todavía no, y entonces es NULL, pero es el mismo NULL para las dos filas que coincidan).

Ninguno de los dos atributos por separado bastaría. ejemplar_cod → fecha_devolucion es falsa: el ejemplar EJ-3081 aparece en dos filas con fechas de devolución distintas (2026-03-16 y NULL). Con encontrar dos filas que la incumplan, la dependencia queda refutada.

Dependencias con varios atributos a la derecha

También el lado derecho puede tener varios:

socio_email → {socio_nombre, socio_telefono}

"El correo del socio determina su nombre y su teléfono". Como veremos en la sección 11, una dependencia así siempre se puede partir en varias con un solo atributo a la derecha, y al revés. Es cuestión de comodidad de escritura.

Las dependencias de prestamos_hoja

Reunidas todas, este es el conjunto de dependencias funcionales que rigen nuestra tabla. Llamaremos F a este conjunto (por functional dependencies), y lo usaremos durante toda la lección:

F = {
  f1:  {ejemplar_cod, fecha_prestamo} → {socio_email, fecha_devolucion}
  f2:  ejemplar_cod    → {isbn, sucursal_nombre}
  f3:  isbn            → {titulo, autor}
  f4:  autor           → autor_nac
  f5:  socio_email     → {socio_nombre, socio_telefono}
  f6:  sucursal_nombre → sucursal_cp
  f7:  sucursal_cp     → sucursal_ciudad
}

Léelas una a una en voz alta, en su versión de prohibición:

Dep. Lectura llana Regla de negocio de la que sale
f1 Un ejemplar en una fecha dada corresponde a un solo préstamo Solo hay una copia física: no se puede prestar dos veces a la vez
f2 Un ejemplar es de un solo título y vive en una sola sucursal Cada copia se cataloga una vez y tiene una sucursal asignada
f3 Un ISBN corresponde a un título y un autor Definición del ISBN como identificador de edición
f4 Un autor tiene una nacionalidad Regla de catalogación de BiblioRed
f5 Un correo identifica a un socio, con su nombre y teléfono El correo es único por socio (era UNIQUE ya en 02-02)
f6 Una sucursal está en un código postal Cada sucursal tiene una dirección
f7 Un código postal está en una ciudad Los códigos postales no se reparten entre municipios

  1. De dónde salen las dependencias: reglas de negocio, no datos de muestra

Este apartado es corto y es, probablemente, el más importante de la lección.

Las dependencias funcionales se descubren preguntando a quien conoce el negocio, no mirando los datos.

La razón es de lógica elemental. Una dependencia X → Y afirma algo sobre todas las filas que puedan existir jamás, incluidas las que aún no se han insertado. Los datos de muestra solo pueden hacer dos cosas:

  • Refutar una dependencia: si encuentras dos filas con el mismo X y distinto Y, la dependencia es falsa. Esto sí es concluyente.
  • No refutarla: si no encuentras contraejemplos, la dependencia podría ser cierta. Esto no demuestra nada.

Un ejemplo con nuestra tabla. Mira las cinco filas y verás que se cumple socio_telefono → socio_email: cada teléfono aparece siempre con el mismo correo. ¿Es una dependencia funcional? Preguntemos a BiblioRed: "¿puede haber dos socios con el mismo teléfono?". Respuesta: "Claro, un matrimonio que da el fijo de casa, o dos hermanos adolescentes que dan el número de su madre". No es una dependencia. Era una coincidencia de la muestra.

Otro ejemplo, en la dirección contraria. En las cinco filas, sucursal_ciudad es siempre Vallmar, así que aparentemente titulo → sucursal_ciudad se cumple (todo lo determina, porque solo hay un valor). Es obviamente absurdo. Con una muestra suficientemente pequeña, "se cumplen" dependencias disparatadas.

Si te toca normalizar una base de datos existente y no hay nadie a quien preguntar, se puede usar el análisis de datos como punto de partida para formular hipótesis, y hay herramientas que buscan candidatas automáticamente. Pero cada candidata hay que validarla contra el negocio antes de convertirla en una decisión de diseño. Una dependencia adoptada por error hace que descompongas donde no debías y que la base de datos rechace datos legítimos el día que aparezcan.

Regla práctica: convierte cada dependencia en una frase que empiece por "no puede ocurrir que…" y llévala a la reunión. isbn → titulo se convierte en "no puede ocurrir que el mismo ISBN tenga dos títulos distintos". Si la persona del negocio duda o dice "bueno, salvo cuando…", no tienes una dependencia: tienes que seguir investigando.

  1. Tipos de dependencia: total, parcial y transitiva

Con la definición ya podemos clasificar. Estos tres tipos son exactamente los que necesitaremos en la lección siguiente para definir la segunda y la tercera forma normal, así que conviene tenerlos claros.

Antes hace falta un término: una superclave es un conjunto de atributos que determina todos los demás atributos de la relación. Una clave candidata es una superclave mínima: si le quitas cualquier atributo, deja de determinarlo todo. Volveremos sobre esto en la sección 13 con un procedimiento para calcularlas; por ahora nos basta con saber que en prestamos_hoja la clave candidata es {ejemplar_cod, fecha_prestamo}.

7.1 Dependencia funcional total (o completa)

X → Y es total si Y depende de X entero: al quitar cualquier atributo de X, la dependencia deja de cumplirse.

Ejemplo en BiblioRed:

{ejemplar_cod, fecha_prestamo} → fecha_devolucion     ← TOTAL

Es total porque ninguna de las dos mitades basta:

  • ejemplar_cod → fecha_devolucion es falsa: EJ-3081 tiene dos fechas de devolución distintas en la muestra.
  • fecha_prestamo → fecha_devolucion es falsa: dos préstamos del mismo día se devuelven en días distintos.

Hacen falta los dos atributos, y por eso la dependencia es total. Las dependencias totales de la clave son las buenas: son exactamente las que queremos que sobrevivan a la normalización.

7.2 Dependencia parcial

X → Y es parcial si X es una clave compuesta (de dos o más atributos) y Y ya queda determinado por una parte de X.

Ejemplo en BiblioRed:

ejemplar_cod → isbn                                   ← PARCIAL respecto de la clave

isbn es un atributo de la tabla que depende de la clave {ejemplar_cod, fecha_prestamo} —como todo lo demás—, pero le sobra la mitad de la clave: ejemplar_cod solo ya lo determina. El código de un ejemplar dice qué obra es, independientemente de cuándo se prestara.

Qué daño hace: el ISBN, el título y el autor se repiten en cada préstamo de ese ejemplar. Son un hecho sobre el ejemplar, no sobre el préstamo, y están almacenados una vez por préstamo. Es la fuente directa de las anomalías de la sección 4.

Lo mismo vale para ejemplar_cod → sucursal_nombre: la sucursal donde vive la copia no depende de cuándo se prestó.

Fíjate en un detalle: una tabla con clave de un solo atributo no puede tener dependencias parciales, porque no hay "partes" de la clave. Es un dato útil cuando llegue la segunda forma normal.

7.3 Dependencia transitiva

X → Z es transitiva si existe un conjunto intermedio Y tal que X → Y e Y → Z, siendo Y no una superclave y Z un atributo que no forma parte de ninguna clave.

En cristiano: el atributo no depende de la clave directamente, sino "a través de" otro atributo que tampoco es clave.

Ejemplo en BiblioRed:

{ejemplar_cod, fecha_prestamo} → socio_email → socio_nombre

El nombre del socio depende de la clave del préstamo, sí, pero solo porque la clave determina el correo y el correo determina el nombre. socio_email no es clave de la tabla; es un atributo cualquiera que resulta que determina a otros. La dependencia real es socio_email → socio_nombre, y el préstamo no pinta nada en ella.

Otro ejemplo, en cadena de tres saltos:

ejemplar_cod → isbn → autor → autor_nac

Para saber la nacionalidad del autor de un préstamo hay que pasar por el ejemplar, el ISBN y el autor. Cuatro escalones, ninguno de ellos clave salvo el primero, y el resultado repetido en cada fila.

Y el más limpio de todos, que reaparecerá en la lección siguiente:

sucursal_nombre → sucursal_cp → sucursal_ciudad

La ciudad no es un hecho sobre la sucursal: es un hecho sobre el código postal. Que la sucursal Norte esté en Vallmar es una consecuencia de que esté en el 08110 y de que el 08110 sea de Vallmar.

Qué daño hace: exactamente el mismo que la parcial. Un hecho que pertenece a otra entidad se repite en todas las filas de esta.

Resumen de los tres tipos

Tipo Forma Ejemplo en prestamos_hoja ¿Problemática?
Total Todo el determinante hace falta {ejemplar_cod, fecha_prestamo} → fecha_devolucion No: es la deseable
Parcial Basta una parte de la clave compuesta ejemplar_cod → isbn Sí: la elimina la 2FN
Transitiva Se llega por un atributo que no es clave sucursal_cp → sucursal_ciudad Sí: la elimina la 3FN

  1. Dependencias triviales

Una dependencia es trivial cuando el lado derecho ya está contenido en el izquierdo:

{ejemplar_cod, fecha_prestamo} → ejemplar_cod        ← trivial
isbn → isbn                                          ← trivial
{isbn, titulo} → titulo                              ← trivial

Se llaman triviales porque se cumplen siempre, en cualquier tabla, sin que nadie tenga que decidirlo: si dos filas coinciden en {ejemplar_cod, fecha_prestamo}, evidentemente coinciden en ejemplar_cod, que es una de esas dos columnas. No aportan ninguna información sobre el diseño.

El símbolo que se usa para expresarlo es , que se lee "está contenido en" o "es subconjunto de". Y ⊆ X significa que todos los elementos de Y están también en X. Con esa notación:

X → Y es trivial si Y ⊆ X. En caso contrario es no trivial. Si además X e Y no comparten ningún atributo, se dice que es completamente no trivial.

¿Para qué sirven, entonces? Para dos cosas. Primero, porque son la base del primer axioma de Armstrong (sección 10) y hacen que la teoría sea completa y sin casos especiales. Segundo, porque las definiciones formales de las formas normales excluyen explícitamente las triviales, y si no supieras qué son, esas definiciones te parecerían incomprensibles. Cuando en 05-02 leas "para toda dependencia no trivial X → Y…", ya sabes qué se está descartando y por qué.

  1. El grafo de dependencias de prestamos_hoja

Las dependencias se ven mucho mejor dibujadas. Cada flecha del diagrama es una dependencia funcional del conjunto F:

flowchart LR
    subgraph CK["Clave candidata"]
        EC["ejemplar_cod"]
        FP["fecha_prestamo"]
    end

    CK ==>|f1| SE["socio_email"]
    CK ==>|f1| FD["fecha_devolucion"]

    EC -->|f2| ISBN["isbn"]
    EC -->|f2| SUN["sucursal_nombre"]

    ISBN -->|f3| TIT["titulo"]
    ISBN -->|f3| AUT["autor"]
    AUT -->|f4| NAC["autor_nac"]

    SE -->|f5| SNO["socio_nombre"]
    SE -->|f5| STE["socio_telefono"]

    SUN -->|f6| CP["sucursal_cp"]
    CP -->|f7| CIU["sucursal_ciudad"]

El grafo cuenta la historia entera de un vistazo, y merece la pena mirarlo despacio:

  • Las dos flechas gruesas salen de la clave completa. Son las dependencias sanas: socio_email y fecha_devolucion son hechos genuinos sobre el préstamo.
  • Las flechas que salen de ejemplar_cod solo (f2) son las dependencias parciales. Media clave determina cosas: ahí hay una tabla escondida.
  • Las cadenas largas (isbn → autor → autor_nac, sucursal_nombre → sucursal_cp → sucursal_ciudad, socio_email → socio_nombre) son las dependencias transitivas. Cada eslabón intermedio que no es clave delata otra tabla escondida.
  • Cada nodo del que sale al menos una flecha y que no es la claveejemplar_cod, isbn, autor, socio_email, sucursal_nombre, sucursal_cpes una entidad disfrazada de columna. Cuenta cuántos hay: seis. En la lección 05-03 esa cuenta se convertirá en seis tablas.

Este es el momento en que la teoría y la intuición del módulo 4 se encuentran. Cuando allí dijimos "una fila de prestamos debe hablar solo del préstamo", lo que estábamos diciendo sin saberlo era: "en el grafo de dependencias, todas las flechas deben salir de la clave completa".

  1. Los axiomas de Armstrong

Tenemos un conjunto F de siete dependencias que nos ha dado el negocio. Pero de ellas se deducen otras que nadie ha escrito. Por ejemplo, de isbn → autor y autor → autor_nac se deduce obviamente isbn → autor_nac, aunque no esté en la lista.

En 1974, William Armstrong publicó tres reglas que permiten deducir todas las dependencias que se siguen de un conjunto dado, y solo esas. Se llaman axiomas de Armstrong. Un axioma es una regla que se acepta como punto de partida y a partir de la cual se demuestra lo demás; que estos tres sean suficientes para deducirlo todo es un teorema demostrado, no una opinión.

El conjunto de todas las dependencias deducibles de F se llama el cierre de F y se escribe F⁺ (con un signo + en superíndice, que en esta teoría significa siempre "todo lo que se deduce de esto").

Axioma 1: Reflexividad

Si Y ⊆ X, entonces X → Y.

En lenguaje llano: un conjunto de columnas determina cualquier subconjunto de sí mismo.

Es la formalización de las dependencias triviales de la sección 8. Parece una tontería, y en cierto modo lo es, pero sin ella la teoría no cierra.

Ejemplo: {isbn, titulo} → titulo. Si dos filas coinciden en ISBN y título, coinciden en título.

Axioma 2: Aumento

Si X → Y, entonces XZ → YZ para cualquier conjunto Z.

En lenguaje llano: si unas columnas determinan otras, añadir las mismas columnas extra a ambos lados no rompe nada. Saber más nunca puede determinar menos.

Ejemplo: sabemos que isbn → titulo. Por aumento con Z = {fecha_prestamo}:

{isbn, fecha_prestamo} → {titulo, fecha_prestamo}

Que se lee: "conocidos el ISBN y la fecha del préstamo, quedan determinados el título y la fecha del préstamo". Es cierto, aunque poco útil por sí solo. Su valor está en combinarlo con los otros axiomas.

Axioma 3: Transitividad

Si X → Y e Y → Z, entonces X → Z.

En lenguaje llano: las dependencias se encadenan.

Este es el axioma que hace trabajo de verdad. Ejemplo en BiblioRed, con dos aplicaciones seguidas:

Sabemos:   isbn  → autor          (f3)
Sabemos:   autor → autor_nac      (f4)
Por transitividad:  isbn → autor_nac

Sabemos:   ejemplar_cod → isbn    (f2)
Acabamos de deducir: isbn → autor_nac
Por transitividad:  ejemplar_cod → autor_nac

Hemos demostrado que el código del ejemplar determina la nacionalidad del autor. Nadie escribió esa regla; se deduce. Y es exactamente por eso que la nacionalidad de Ken Follett aparece repetida en cada préstamo de cada uno de sus ejemplares.

  1. Las reglas derivadas: unión, descomposición, pseudotransitividad

De los tres axiomas se deducen otras reglas que no añaden poder —todo lo que se demuestra con ellas se podría demostrar con los tres axiomas— pero que acortan muchísimo el trabajo a mano.

Unión

Si X → Y y X → Z, entonces X → YZ.

Llano: si el mismo determinante determina dos cosas por separado, las determina juntas.

Ejemplo: de socio_email → socio_nombre y socio_email → socio_telefono se obtiene socio_email → {socio_nombre, socio_telefono}. Es justo lo que escribimos como f5.

Descomposición

Si X → YZ, entonces X → Y y X → Z.

Llano: es la regla anterior al revés. Una dependencia con varias columnas a la derecha se puede partir en varias con una sola.

Ejemplo: de f2, ejemplar_cod → {isbn, sucursal_nombre}, se obtienen ejemplar_cod → isbn y ejemplar_cod → sucursal_nombre.

Unión y descomposición juntas dicen algo práctico: el lado derecho de una dependencia se puede agrupar o desagrupar libremente. Por eso, cuando hay que trabajar a mano, se suele empezar descomponiendo todas las dependencias para que tengan un solo atributo a la derecha. Nuestro conjunto F quedaría así:

F (en forma desagregada, 11 dependencias):
  {ejemplar_cod, fecha_prestamo} → socio_email
  {ejemplar_cod, fecha_prestamo} → fecha_devolucion
  ejemplar_cod    → isbn
  ejemplar_cod    → sucursal_nombre
  isbn            → titulo
  isbn            → autor
  autor           → autor_nac
  socio_email     → socio_nombre
  socio_email     → socio_telefono
  sucursal_nombre → sucursal_cp
  sucursal_cp     → sucursal_ciudad

Ojo: el lado izquierdo no se puede partir así. De {ejemplar_cod, fecha_prestamo} → socio_email no se sigue ejemplar_cod → socio_email. Este es un error clásico y produce descomposiciones desastrosas.

Pseudotransitividad

Si X → Y e YW → Z, entonces XW → Z.

Llano: una transitividad en la que el segundo paso necesita ayuda extra. Si X me da Y, y con Y más W llego a Z, entonces con X más W también llego a Z.

Ejemplo: supongamos que BiblioRed calcula el recargo por retraso con una tarifa que depende de la sucursal y del número de días: {sucursal_nombre, dias_retraso} → recargo. Como ejemplar_cod → sucursal_nombre, por pseudotransitividad:

{ejemplar_cod, dias_retraso} → recargo

Conocidos el ejemplar y los días de retraso, el recargo queda determinado: el ejemplar aporta la sucursal.

Las seis reglas juntas

Regla Enunciado Tipo
Reflexividad Y ⊆ XX → Y Axioma
Aumento X → YXZ → YZ Axioma
Transitividad X → Y, Y → ZX → Z Axioma
Unión X → Y, X → ZX → YZ Derivada
Descomposición X → YZX → Y, X → Z Derivada
Pseudotransitividad X → Y, YW → ZXW → Z Derivada

  1. El cierre de un conjunto de atributos (X⁺)

Aplicar los axiomas a mano para responder "¿se deduce X → Y de F?" es lento y propenso a errores. Existe un algoritmo mecánico que lo resuelve, y es la herramienta más útil de toda la teoría de normalización.

Definición. El cierre de un conjunto de atributos X respecto de un conjunto de dependencias F, escrito X⁺, es el conjunto de todos los atributos que quedan determinados por X usando las dependencias de F.

Dicho de otro modo: X⁺ responde a la pregunta "si conozco los valores de X, ¿qué más puedo averiguar?".

El algoritmo, paso a paso

ENTRADA: un conjunto de atributos X, un conjunto de dependencias F
SALIDA:  X⁺

1. Empieza con  RESULTADO = X          (lo que conoces de entrada)
2. Repite mientras RESULTADO cambie:
       Para cada dependencia  A → B  de F:
           Si todos los atributos de A están ya en RESULTADO:
               Añade todos los atributos de B a RESULTADO
3. Devuelve RESULTADO

La idea es la de una bola de nieve: partes de lo que sabes, aplicas todas las reglas que puedas, y con lo nuevo que has averiguado vuelves a intentarlo, hasta que una pasada completa no añada nada.

Solo hay que vigilar una cosa, y es la misma trampa que antes: para disparar una dependencia A → B hacen falta todos los atributos de A en RESULTADO, no basta con alguno.

Ejemplo 1: {ejemplar_cod}⁺

Pregunta: conocido solo el código del ejemplar, ¿qué sé de un préstamo?

Pasada Dependencia aplicable RESULTADO después
Inicio {ejemplar_cod}
1 ejemplar_cod → isbn {ejemplar_cod, isbn}
1 ejemplar_cod → sucursal_nombre {ejemplar_cod, isbn, sucursal_nombre}
1 isbn → titulo + titulo
1 isbn → autor + autor
1 autor → autor_nac + autor_nac
1 sucursal_nombre → sucursal_cp + sucursal_cp
1 sucursal_cp → sucursal_ciudad + sucursal_ciudad
2 (ninguna nueva aplicable)
{ejemplar_cod}⁺ = {ejemplar_cod, isbn, titulo, autor, autor_nac,
                   sucursal_nombre, sucursal_cp, sucursal_ciudad}

Ocho atributos de trece. Faltan fecha_prestamo, fecha_devolucion, socio_email, socio_nombre y socio_telefono. Conclusión formal: ejemplar_cod no es una superclave de prestamos_hoja, porque su cierre no contiene todos los atributos.

Y una lectura importante: esos ocho atributos que sí determina son precisamente los que estarán repetidos en cada préstamo del mismo ejemplar. El cierre de un atributo que no es clave mide la redundancia que ese atributo genera.

Ejemplo 2: {socio_email}⁺

Pasada Dependencia aplicable RESULTADO después
Inicio {socio_email}
1 socio_email → socio_nombre + socio_nombre
1 socio_email → socio_telefono + socio_telefono
2 (ninguna)
{socio_email}⁺ = {socio_email, socio_nombre, socio_telefono}

Tres atributos. Tampoco es superclave. Y de nuevo el cierre dibuja una tabla que está pidiendo existir: socios(email, nombre, telefono).

Ejemplo 3: {ejemplar_cod, fecha_prestamo}⁺

Pasada Dependencia aplicable RESULTADO después
Inicio {ejemplar_cod, fecha_prestamo}
1 {ejemplar_cod, fecha_prestamo} → socio_email + socio_email
1 {ejemplar_cod, fecha_prestamo} → fecha_devolucion + fecha_devolucion
1 ejemplar_cod → isbn + isbn
1 ejemplar_cod → sucursal_nombre + sucursal_nombre
1 isbn → titulo, isbn → autor + titulo, autor
1 autor → autor_nac + autor_nac
1 socio_email → socio_nombre, → socio_telefono + socio_nombre, socio_telefono
1 sucursal_nombre → sucursal_cp + sucursal_cp
1 sucursal_cp → sucursal_ciudad + sucursal_ciudad
2 (ninguna nueva)
{ejemplar_cod, fecha_prestamo}⁺ = los 13 atributos de la tabla

Contiene todos los atributos. Por definición, {ejemplar_cod, fecha_prestamo} es una superclave.

Para qué sirve el cierre

Pregunta Cómo se responde con el cierre
¿Se deduce X → Y de F? Calcula X⁺. Si Y ⊆ X⁺, sí.
¿Es X una superclave? Calcula X⁺. Si contiene todos los atributos, sí.
¿Es X una clave candidata? Es superclave y ningún subconjunto propio suyo lo es.
¿Cuánta redundancia genera X? El tamaño de X⁺ cuando X no es clave.

  1. Encontrar las claves candidatas con el cierre

Ya tenemos todo para resolver el problema práctico central: dada una relación y sus dependencias, ¿cuáles son sus claves?

El procedimiento sistemático se apoya en una observación muy útil que ahorra la mayor parte del trabajo. Clasifica cada atributo según dónde aparece en F:

Categoría Dónde aparece Consecuencia
Solo a la izquierda En algún determinante, en ningún lado derecho Está en todas las claves candidatas
Solo a la derecha En algún lado derecho, en ningún determinante No está en ninguna clave candidata
En ambos lados Aparece a izquierda y a derecha Puede estar o no: hay que probar
En ninguno No aparece en F Está en todas las claves candidatas

La razón de la primera regla es intuitiva: si un atributo nunca aparece a la derecha, ninguna dependencia lo puede producir, así que la única forma de conocerlo es tenerlo de entrada. Y la razón de la segunda: si aparece solo a la derecha, siempre puede deducirse de otros, así que nunca hace falta en un conjunto mínimo.

Aplicado a prestamos_hoja, paso a paso

Paso 1. Clasificar los trece atributos.

Atributo ¿Izquierda? ¿Derecha? Categoría
ejemplar_cod Sí (f1, f2) No Solo izquierda
fecha_prestamo Sí (f1) No Solo izquierda
socio_email Sí (f5) Sí (f1) Ambos
isbn Sí (f3) Sí (f2) Ambos
autor Sí (f4) Sí (f3) Ambos
sucursal_nombre Sí (f6) Sí (f2) Ambos
sucursal_cp Sí (f7) Sí (f6) Ambos
fecha_devolucion No Sí (f1) Solo derecha
socio_nombre No Sí (f5) Solo derecha
socio_telefono No Sí (f5) Solo derecha
titulo No Sí (f3) Solo derecha
autor_nac No Sí (f4) Solo derecha
sucursal_ciudad No Sí (f7) Solo derecha

Paso 2. El núcleo obligatorio. Los atributos "solo izquierda" están en toda clave candidata: {ejemplar_cod, fecha_prestamo}.

Paso 3. ¿Basta con el núcleo? Calculamos su cierre, que ya hicimos en el ejemplo 3 de la sección anterior:

{ejemplar_cod, fecha_prestamo}⁺ = los 13 atributos

Sí basta. Es superclave.

Paso 4. ¿Es mínima? Hay que comprobar que ningún subconjunto propio lo sea. Los subconjuntos propios de un conjunto de dos elementos son tres: {ejemplar_cod}, {fecha_prestamo} y el conjunto vacío.

  • {ejemplar_cod}⁺ = 8 atributos. No es superclave (calculado en 12.1).
  • {fecha_prestamo}⁺ = {fecha_prestamo}. Ninguna dependencia tiene fecha_prestamo sola a la izquierda, así que el cierre no crece. No es superclave.
  • El conjunto vacío, obviamente, tampoco.

Paso 5. Conclusión. {ejemplar_cod, fecha_prestamo} es superclave y es mínima, luego es una clave candidata. Y como todo atributo "solo izquierda" debe estar en toda clave candidata, y estos dos ya bastan por sí solos, es la única.

Queda demostrado lo que en la sección 3 dimos por bueno. Esta es la diferencia entre diseñar por intuición y diseñar con instrumental: ahora no lo creemos, lo sabemos.

Un caso con dos claves candidatas

Para que veas que la unicidad no está garantizada, tomemos la tabla socios del esquema real de BiblioRed, con estas dependencias:

socio_id → {nombre, apellidos, email, fecha_alta, sucursal_id, activo}
email    → {socio_id, nombre, apellidos, fecha_alta, sucursal_id, activo}

La segunda existe porque email es UNIQUE (lo declaramos así en 02-02). Calculemos:

  • {socio_id}⁺ = todos los atributos → superclave, y mínima (es un solo atributo).
  • {email}⁺ = todos los atributos → superclave, y mínima.

Dos claves candidatas: {socio_id} y {email}. Una se elige como primaria —socio_id, la subrogada, por las razones que discutimos en 04-01— y la otra queda como clave alternativa, protegida con UNIQUE. Esto no es un defecto de diseño; es lo normal cuando una entidad tiene a la vez clave natural y clave subrogada.

  1. Atributos primos y no primos

Última definición de la lección, y la más corta. La necesitaremos literalmente en la primera frase de la segunda y la tercera forma normal.

Un atributo es primo (o atributo clave) si forma parte de alguna clave candidata de la relación. Si no forma parte de ninguna, es no primo (o atributo no clave).

Ojo al "alguna": si una relación tiene dos claves candidatas, basta con estar en una de ellas para ser primo.

En prestamos_hoja, con su única clave candidata {ejemplar_cod, fecha_prestamo}:

Atributos primos (2) Atributos no primos (11)
ejemplar_cod, fecha_prestamo fecha_devolucion, socio_email, socio_nombre, socio_telefono, isbn, titulo, autor, autor_nac, sucursal_nombre, sucursal_ciudad, sucursal_cp

Once atributos no primos, cada uno de ellos colgando de la clave por dependencias parciales o transitivas. La tabla está, formalmente hablando, tan mal como parecía.

En socios, con claves candidatas {socio_id} y {email}, son primos los dos: socio_id y email. Todos los demás son no primos. Este ejemplo suele sorprender: email es un atributo de aspecto totalmente corriente y sin embargo es primo, porque es clave candidata.

Errores Comunes y Consejos

Confundir "normalizar" con "tener muchas tablas". El número de tablas es una consecuencia, no un objetivo. Si al descomponer no puedes nombrar la dependencia problemática que estás eliminando, no estás normalizando: estás complicando el esquema. Ante la duda, escribe la dependencia en un papel antes de tocar el CREATE TABLE.

Deducir dependencias de los datos de muestra. Es el error más caro de todos, porque no se detecta hasta que el sistema está en producción y rechaza un dato legítimo. Toda dependencia debe venir de una regla de negocio confirmada. Si BiblioRed dice "en principio cada ISBN tiene un título", ese "en principio" es una alarma: pregunta por las excepciones antes de escribirla.

Invertir la flecha. isbn → titulo no es lo mismo que titulo → isbn, y la segunda es falsa (varias ediciones comparten título). Cuando dudes de la dirección, usa la formulación de prohibición: "¿puede haber un ISBN con dos títulos?" (no → la dependencia va de ISBN a título) frente a "¿puede haber un título con dos ISBN?" (sí → no hay dependencia en ese sentido).

Partir el lado izquierdo de una dependencia. De {A, B} → C no se sigue A → C ni B → C. El lado derecho sí se puede partir (regla de descomposición); el izquierdo, jamás. Aplicar esta falsa regla al calcular un cierre produce claves candidatas inventadas y descomposiciones que pierden información.

Olvidar que un solo contraejemplo refuta. Para demostrar que una dependencia es falsa basta encontrar dos filas con el mismo determinante y distinto determinado. Es la comprobación más barata que existe y siempre vale la pena hacerla antes de aceptar una dependencia. En SQL:

-- ¿Se cumple realmente  isbn → titulo  en los datos actuales?
-- Si devuelve alguna fila, la dependencia está violada HOY.
SELECT isbn, COUNT(DISTINCT titulo) AS titulos_distintos
FROM prestamos_hoja
GROUP BY isbn
HAVING COUNT(DISTINCT titulo) > 1;

Ojo: que devuelva cero filas no demuestra la dependencia (sección 6), pero que devuelva alguna sí la refuta, o bien indica que hay datos sucios que limpiar. En el fichero original de BiblioRed esta consulta devolvía filas, precisamente por el ISBN truncado.

Detenerse a la primera pasada al calcular un cierre. El algoritmo repite hasta que nada cambia. Es muy fácil añadir isbn y olvidar que ahora, con isbn dentro, se dispara isbn → autor, y con autor dentro se dispara autor → autor_nac. Marca las dependencias ya usadas y vuelve a recorrer la lista entera después de cada incorporación.

Consejo de método: para calcular cierres a mano, escribe las dependencias en forma desagregada (un solo atributo a la derecha) y ve tachándolas conforme las usas. Es mucho más difícil equivocarse.

Ejercicios

Ejercicio 1: Identificar la anomalía

BiblioRed mantiene una tabla plana eventos_hoja con esta estructura, heredada de otra hoja de cálculo:

eventos_hoja(evento_id, titulo_evento, fecha, sala_nombre, sala_aforo, sala_planta, ponente_email, ponente_nombre)

Para cada una de estas tres situaciones, di qué anomalía es (inserción, actualización o borrado) y qué dependencia funcional la provoca:

  • a) La sala Polivalente de Centro se reforma y su aforo pasa de 60 a 90 plazas. Hay 214 eventos celebrados en ella.
  • b) BiblioRed habilita una sala nueva, la Sala Infantil de Este, con aforo 25. Todavía no hay ningún evento programado en ella.
  • c) Se cancela y se borra el único evento en el que participó la ponente Clara Ferrán.

Ejercicio 2: Calcular un cierre y decidir si es clave

Sobre la relación:

R(evento_id, socio_email, socio_nombre, fecha_insc, estado, acompanantes, plazas_ocupadas)

con el conjunto de dependencias:

g1: {evento_id, socio_email} → {fecha_insc, estado, acompanantes}
g2: socio_email  → socio_nombre
g3: acompanantes → plazas_ocupadas

Se pide:

  • a) Calcular {evento_id, socio_email}⁺ mostrando las pasadas.
  • b) Decir si es superclave y si es clave candidata, justificándolo.
  • c) Calcular {socio_email}⁺ y decir qué significa el resultado.
  • d) Listar los atributos primos y los no primos.

Ejercicio 3: Clasificar dependencias

En la relación prestamos_hoja de esta lección, clasifica cada una de estas cinco dependencias como total, parcial, transitiva o trivial respecto de la clave candidata {ejemplar_cod, fecha_prestamo}. Justifica cada una en una frase.

  • a) {ejemplar_cod, fecha_prestamo} → socio_email
  • b) ejemplar_cod → sucursal_nombre
  • c) {ejemplar_cod, fecha_prestamo} → sucursal_ciudad
  • d) {ejemplar_cod, isbn} → ejemplar_cod
  • e) socio_email → socio_telefono

Soluciones

Solución 1

a) Anomalía de actualización. La dependencia culpable es sala_nombre → sala_aforo: el aforo es un hecho sobre la sala, pero está almacenado una vez por evento. Cambiarlo obliga a un UPDATE de 214 filas, y si alguna se queda fuera —por un filtro mal escrito, por una diferencia de mayúsculas en el nombre de la sala— BiblioRed tendrá la misma sala con dos aforos. Es exactamente el caso "Norte"/"norte" trasladado a las salas.

b) Anomalía de inserción. La misma dependencia, sala_nombre → {sala_aforo, sala_planta}, vista desde el otro lado. Los datos de la sala solo pueden guardarse colgados de un evento, y esta sala no tiene ninguno. La única alternativa sería insertar un evento fantasma con titulo_evento y fecha inventados, que contaminaría cualquier consulta sobre eventos.

c) Anomalía de borrado. La dependencia es ponente_email → ponente_nombre. Al borrar el evento desaparece también el único registro que decía que existe una ponente llamada Clara Ferrán con ese correo. La información sobre la ponente no tenía existencia propia: vivía de prestado en la fila del evento.

Las tres tienen la misma raíz: hay dependencias cuyo determinante (sala_nombre, ponente_email) no es clave de la tabla. Son entidades —salas, ponentes— disfrazadas de columnas. Y no por casualidad: en el esquema real del módulo 4, BiblioRed ya las tiene como tablas propias.

Solución 2

a) Cierre de {evento_id, socio_email}:

Pasada Dependencia aplicada RESULTADO
Inicio {evento_id, socio_email}
1 g1 (los dos atributos del determinante están) + fecha_insc, estado, acompanantes
1 g2 (socio_email está) + socio_nombre
1 g3 (acompanantes acaba de entrar) + plazas_ocupadas
2 (ninguna nueva)
{evento_id, socio_email}⁺ = {evento_id, socio_email, fecha_insc, estado,
                             acompanantes, socio_nombre, plazas_ocupadas}

Los siete atributos de R. Nótese el efecto bola de nieve: plazas_ocupadas solo entra después de que entre acompanantes, que a su vez entró por g1. Quien se detenga en la primera dependencia se lo pierde.

b) Es superclave, porque su cierre contiene todos los atributos. Y es clave candidata porque es mínima: hay que comprobar los dos subconjuntos propios de un elemento.

  • {evento_id}⁺ = {evento_id}. evento_id no aparece solo a la izquierda de ninguna dependencia (en g1 va acompañado), así que el cierre no crece. No es superclave.
  • {socio_email}⁺ = ver apartado c). No es superclave.

Como ningún subconjunto propio es superclave, {evento_id, socio_email} es mínima y por tanto clave candidata.

c) Cierre de {socio_email}:

{socio_email}⁺ = {socio_email, socio_nombre}

Solo g2 es aplicable, y después nada más. Dos atributos de siete. Significa que socio_email no es superclave, y —más interesante— que arrastra consigo un atributo, socio_nombre, que quedará repetido en todas las inscripciones de ese socio. Es una dependencia parcial de la clave compuesta, la señal inequívoca de que el nombre del socio no pinta nada en esta tabla y debe vivir en socios. En el esquema real de BiblioRed, inscripciones no tiene socio_nombre, y ahora sabemos formalmente por qué.

d) La única clave candidata es {evento_id, socio_email}.

  • Primos: evento_id, socio_email.
  • No primos: fecha_insc, estado, acompanantes, socio_nombre, plazas_ocupadas.

Solución 3

a) Total. El determinante es la clave completa y ninguna de sus dos mitades basta: ejemplar_cod → socio_email es falsa (EJ-3081 fue prestado a Marta dos veces distintas, pero podría haberlo sido a otra persona en otra fecha; y en general un ejemplar circula entre socios), y fecha_prestamo → socio_email es evidentemente falsa (el mismo día se prestan libros a varios socios). Es una dependencia sana: socio_email es un hecho genuino sobre el préstamo.

b) Parcial. El determinante ejemplar_cod es una parte propia de la clave compuesta y ya determina sucursal_nombre por sí solo. La fecha del préstamo no interviene: la sucursal donde vive una copia no cambia según cuándo se preste. Es una de las dependencias que eliminará la segunda forma normal.

c) Transitiva. La clave determina sucursal_ciudad, sí, pero por una cadena de tres saltos: {ejemplar_cod, fecha_prestamo} → ejemplar_cod → sucursal_nombre → sucursal_cp → sucursal_ciudad. Ninguno de los eslabones intermedios es superclave y sucursal_ciudad es un atributo no primo, que son las dos condiciones de la transitividad. Es la que eliminará la tercera forma normal.

(Nota: esta dependencia es a la vez parcial, porque ejemplar_cod solo ya la produce. No son categorías excluyentes: una misma dependencia puede ser problemática por más de un motivo, y por eso la normalización se aplica por etapas —primero 2FN, luego 3FN— en lugar de todo a la vez.)

d) Trivial. El lado derecho, {ejemplar_cod}, está contenido en el izquierdo, {ejemplar_cod, isbn}. Se cumple siempre, en cualquier tabla, sin que nadie lo decida. No dice nada sobre el diseño y las definiciones de las formas normales la excluirán explícitamente.

e) Transitiva (respecto de la clave). Por sí sola, socio_email → socio_telefono es simplemente una dependencia; lo que la hace transitiva es su relación con la clave: {ejemplar_cod, fecha_prestamo} → socio_email → socio_telefono, con socio_email no superclave y socio_telefono no primo. Su consecuencia práctica es que el teléfono de Marta Alsina está escrito tres veces en cinco filas.

Conclusión

Esta lección ha construido el instrumental. Recapitulemos lo que ahora está en tu poder y no lo estaba al empezar el módulo.

Sabes qué es normalizar: reorganizar atributos para que cada hecho esté una sola vez, con un procedimiento justificable. Y sabes qué no es: ni partir tablas por deporte, ni un fin en sí mismo, ni limpiar datos sucios. Sabes también que el enemigo no es el espacio en disco sino la posibilidad física de la contradicción, y que todo lo que es posible acaba ocurriendo.

Sabes nombrar el daño. Las tres anomalías —de inserción, de actualización y de borrado— dejaron de ser una tabla de tres líneas del módulo 4 para convertirse en tres fallos concretos que has visto provocar con INSERT, UPDATE y DELETE sobre la hoja de BiblioRed. Y sabes que las tres tienen una única causa estructural.

Sabes escribir la causa. X → Y, "X determina Y", con su determinante y su determinado, con su dirección que no se puede invertir, y con la advertencia capital de que sale de las reglas del negocio y nunca de los datos de muestra. Sabes distinguir las dependencias totales (las sanas), las parciales (media clave determina algo) y las transitivas (se llega por un atributo que no es clave), y sabes descartar las triviales.

Sabes calcular. Los tres axiomas de Armstrong —reflexividad, aumento, transitividad— y sus tres reglas derivadas —unión, descomposición, pseudotransitividad— permiten deducir toda dependencia que se siga de las conocidas. Y el algoritmo del cierre X⁺ convierte en mecánico lo que era intuición: responde si una dependencia se deduce, si un conjunto es superclave y, aplicado con la clasificación de atributos por su posición en F, encuentra las claves candidatas. Lo hemos usado para demostrar que la clave de prestamos_hoja es {ejemplar_cod, fecha_prestamo} y que socios tiene dos claves candidatas.

Y sabes clasificar los atributos en primos (los que forman parte de alguna clave candidata) y no primos (los demás), que es la distinción sobre la que se apoyan literalmente las definiciones que vienen ahora.

Porque lo que viene ahora son las formas normales. Son una escala de niveles de exigencia crecientes: la primera pide poco y casi cualquier tabla razonable la cumple; la segunda añade una condición; la tercera, otra; y así hasta un punto en que las exigencias son tan finas que rara vez se aplican en la práctica. Cada nivel prohíbe un tipo concreto de dependencia mal colocada —y tienes que reconocer todas las que hemos definido en esta lección para entender cuál prohíbe cada uno.

En la lección 05-02, Formas Normales, las recorreremos una a una: primera, segunda, tercera, Boyce-Codd, cuarta y quinta, cada una con su definición precisa, un ejemplo mínimo de BiblioRed que la viola, la corrección correspondiente y el motivo por el que importa. No aplicaremos todavía ninguna metodología sobre la hoja de préstamos —eso es la lección 05-03—: primero hay que tener el catálogo completo.

Fundamentos de Bases de Datos

Módulo 1: Introducción a las Bases de Datos

Módulo 2: Bases de Datos Relacionales

Módulo 3: Bases de Datos No Relacionales

Módulo 4: Diseño de Esquemas

Módulo 5: Normalización

Módulo 6: Transacciones, Rendimiento y Seguridad

Módulo 7: Ejercicios Prácticos

Módulo 8: Casos de Estudio

Módulo 9: Recursos Adicionales

© Copyright 2026. Todos los derechos reservados