La normalización comprueba que los datos están bien repartidos entre tablas: cada dato se guarda una sola vez. El diseño parte del diagrama de clases (tema 01); estas reglas lo validan y detectan los errores que la traducción no muestra.
¿Qué pasa si libros y editoriales se mezclan en una única tabla? Los datos de la editorial se repiten en todas sus filas:
CREATE TABLE book (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(200) NOT NULL,
price DECIMAL(10,2) NOT NULL,
publisher_name VARCHAR(100) NOT NULL,
publisher_city VARCHAR(100) NOT NULL
);
| Anomalía | Con esta tabla |
|---|---|
| Inserción | No se puede guardar una editorial sin que tenga libros: no hay fila donde poner sus datos |
| Actualización | Cambiar la ciudad de una editorial obliga a actualizar todas sus filas; si una se queda atrás, la tabla se contradice |
| Borrado | Borrar el último libro de una editorial borra también sus datos |
La redundancia es la causa: el mismo dato, copiado en muchas filas, se actualiza — o se pierde — de forma incompleta. Se corrige al llegar a la tercera forma normal.
Cada valor debe ser atómico: una columna guarda un dato simple, no una colección:
-- mal: la colección de autores dentro de la fila del libro
CREATE TABLE book (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(200) NOT NULL,
author_names VARCHAR(400) NOT NULL -- 'Robert Martin, Martin Fowler'
);
Tampoco valen los grupos repetitivos: columnas gemelas tipo author1, author2…, que obligan a estimar cuántas hacen falta y dejan huecos vacíos.
La solución es la del modelo relacional: las colecciones se convierten en tablas. En este caso, la tabla de unión book_author vista en el tema 01.
Con clave primaria compuesta, cada columna debe depender de la clave completa, no de una parte:
CREATE TABLE book_author (
book_id BIGINT NOT NULL,
author_id BIGINT NOT NULL,
author_nationality VARCHAR(80), -- depende solo de author_id
PRIMARY KEY (book_id, author_id)
);
author_nationality cambia con el autor, no con el par (libro, autor): se repetiría en todos los libros de un autor y una actualización a medias lo rompería. La columna pertenece a la tabla author, cuya clave es la que la determina.
Cada columna debe depender solo de la clave primaria, no de otra columna no clave (dependencia transitiva). En la tabla del apartado 1: id → publisher_city → publisher_name.
La corrección crea una tabla para la editorial y deja en book solo la clave foránea:
CREATE TABLE publisher (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
city VARCHAR(100) NOT NULL
);
CREATE TABLE book (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(200) NOT NULL,
price DECIMAL(10,2) NOT NULL,
publisher_id BIGINT NOT NULL,
FOREIGN KEY (publisher_id) REFERENCES publisher (id)
);
Cada dato se guarda una sola vez: la editorial existe por sí misma y sus libros la referencian.
| Forma | Comprueba que | Solución típica |
|---|---|---|
| 1FN | Los valores son atómicos | Tabla propia para la colección |
| 2FN | Con clave compuesta, todo depende de la clave completa | La columna se va con la tabla de la parte que la determina |
| 3FN | Nadie depende de otra columna no clave | Tabla propia para la entidad dependiente |