¿Qué es normalizar?
Normalizar una base de datos es organizar sus tablas para que cada dato esté guardado en un solo lugar. Se hace repartiendo la información en más tablas, cada una con un tema propio, y uniéndolas por claves.
La idea suena al revés de lo que uno esperaría: para ordenar una base, se la divide en más partes. Pero funciona, y el motivo es simple: si un dato vive en un único lugar, no puede estar mal en dos lugares a la vez.
El proceso tiene etapas
Normalizar no es un acto único, sino una serie de pasos llamados formas normales. Cada forma normal es más exigente que la anterior, y se numeran: primera (1FN), segunda (2FN), tercera (3FN) y hay más.
En la práctica, una base de datos bien diseñada suele llegar hasta la tercera forma normal. Ese es el objetivo habitual, y a partir de ahí las formas siguientes ya resuelven casos muy particulares.
Conviene tener claro desde el principio que normalizar no es un fin en sí mismo: es una herramienta para evitar problemas concretos. Esos problemas son el tema de las dos secciones siguientes, y hay que entenderlos antes de aprenderse las reglas.
El problema: la redundancia
La redundancia es la repetición innecesaria de un mismo dato en varios lugares. Aparece sola cuando se guarda todo en una sola tabla, y es el problema que la normalización viene a resolver.
Un ejemplo concreto
Supongamos una librería que anota sus ventas en una única tabla. Cada venta es una fila, y en cada fila se escribe todo lo que hace falta saber:
| N.º venta | Fecha | Cliente | Teléfono | Producto | Precio |
|---|---|---|---|---|---|
| 1 | 3/3 | Ana Gómez | 555-1234 | Teclado | 15000 |
| 2 | 3/3 | Ana Gómez | 555-1234 | Mouse | 8000 |
| 3 | 4/3 | Ana Gómez | 555-1234 | Monitor | 90000 |
| 4 | 4/3 | Luis Pérez | 555-9876 | Teclado | 15000 |
La tabla funciona: se puede consultar y responde lo que se le pide. ¿Cuál es el problema, entonces? Que el nombre de Ana y su teléfono aparecen tres veces, y el precio del teclado, dos.
Las tres consecuencias
- Se ocupa más espacio. Es el problema menos importante, y el único que se ve a simple vista.
- Los datos se pueden contradecir. Si Ana cambia de teléfono, hay que actualizar todas las filas donde aparece. Si alguna queda sin cambiar, la base de datos dice dos cosas distintas sobre lo mismo, y ya no se sabe cuál es la verdadera.
- Aparecen operaciones que no deberían existir. Cargar un dato obliga a inventar otro; borrar una fila hace perder información que no tenía nada que ver. Son las anomalías de la sección siguiente.
Las tres anomalías
Se llaman anomalías a los problemas que aparecen al hacer operaciones sobre una tabla con redundancia. Son la razón práctica por la que se normaliza: cada forma normal elimina una.
| Anomalía | Qué pasa | Ejemplo con la tabla de ventas |
|---|---|---|
| De inserción | No se puede cargar un dato sin inventar otro que no corresponde. | Para registrar a un cliente nuevo todavía no alcanza con escribir sus datos: hay que inventarle una venta, porque la tabla solo guarda clientes que compraron algo. |
| De actualización | Hay que cambiar el mismo dato en varios lugares, y si se olvida uno quedan datos contradictorios. | Ana cambia de teléfono: hay que actualizarlo en sus tres ventas. Si después hace una cuarta compra y se copia el teléfono viejo, la base queda con dos teléfonos distintos para la misma persona. |
| De borrado | Al borrar una fila se pierde información que no tenía relación con lo que se quería borrar. | Si se anula la venta 1, se pierde el registro de que el teclado cuesta 15000. Se borró la venta y, de paso, un dato del producto. |
Las tres tienen la misma raíz: una sola tabla guardando datos de cosas distintas. La tabla de ventas mezcla datos de la venta (número y fecha), del cliente (nombre y teléfono) y del producto (nombre y precio). En la sección del ejemplo completo se ve cómo se desarma.
Primera forma normal (1FN)
La primera forma normal tiene una sola regla, y es la más fácil de entender:
Cada celda contiene un único valor.
Dicho de otro modo: no se puede guardar una lista dentro de una celda. Y además, la tabla tiene que tener una clave primaria que identifique cada fila.
Cómo se ve una tabla que no cumple 1FN
| N.º venta | Cliente | Productos |
|---|---|---|
| 1 | Ana Gómez | Teclado, Mouse |
| 2 | Luis Pérez | Monitor |
La celda de "Productos" tiene dos valores. Eso trae consecuencias muy concretas: no se puede averiguar fácilmente cuántas veces se vendió un mouse sin buscar dentro del texto, no se puede ordenar por producto, y no se puede poner una restricción que garantice que solo se escriban productos que existen.
La solución es una fila por producto vendido, repitiendo el número de venta:
| N.º venta | Cliente | Producto |
|---|---|---|
| 1 | Ana Gómez | Teclado |
| 1 | Ana Gómez | Mouse |
| 2 | Luis Pérez | Monitor |
Segunda forma normal (2FN)
La segunda forma normal exige dos cosas: cumplir 1FN, y que cada campo dependa de la clave completa y no de una parte de ella.
Esa segunda condición suena complicada, pero aparece solo en un caso: cuando la clave primaria está formada por más de un campo. Si la clave es un solo campo, la 2FN se cumple sola.
El caso típico
En la tabla del paso anterior, la clave primaria es la combinación de N.º venta + Producto: no alcanza con el número de venta, porque una venta puede tener varios productos; y tampoco alcanza con el producto, porque un producto se vende muchas veces.
Ahora, si se le agrega el nombre del producto:
| N.º venta | Producto | Precio del producto |
|---|---|---|
| 1 | Teclado | 15000 |
| 1 | Mouse | 8000 |
| 4 | Teclado | 15000 |
El precio no depende de la venta: el teclado cuesta 15000 en la venta 1 y también en la venta 4. Depende únicamente del producto, que es solo una parte de la clave. Eso es lo que la 2FN prohíbe.
La solución es sacar el producto a su propia tabla, y dejar en la tabla de ventas solo la referencia:
PRODUCTOS VENTAS_DETALLE
------------------------ ------------------------
id ← clave primaria n_venta ← parte de la clave
nombre producto_id ← parte de la clave y foránea
precio
Tercera forma normal (3FN)
La tercera forma normal exige cumplir 2FN y, además, que ningún campo dependa de otro campo que no sea la clave. A esto se lo llama dependencia transitiva: el dato llega a depender de la clave "pasando por" otro campo.
El caso típico
En una tabla de clientes con su dirección:
| Cliente (clave) | Nombre | Código postal | Ciudad |
|---|---|---|---|
| 1 | Ana Gómez | 1900 | La Plata |
| 2 | Luis Pérez | 1900 | La Plata |
La ciudad no depende del cliente: depende del código postal. El cliente 1 y el cliente 2 viven en la misma ciudad porque comparten el código postal, no porque estén relacionados entre sí. Y el problema se ve enseguida: si el código 1900 pasara a llamarse de otra forma, habría que actualizar la ciudad en todos los clientes que viven ahí.
La solución es separar la ciudad:
CODIGOS_POSTALES CLIENTES
---------------------- ----------------------
codigo ← clave primaria id ← clave primaria
ciudad nombre
codigo_postal ← foránea
Un ejemplo completo
El recorrido de las tres formas normales se ve mejor en un caso: llevar una tabla única —con todos sus problemas— hasta un diseño ordenado. Se parte de esta tabla de ventas:
Paso 1: eliminar las listas (1FN)
Si una venta lleva varios productos, no se escriben todos en la misma celda: se abre una fila por producto.
Paso 2: sacar el producto de la tabla de ventas (2FN)
El nombre y el precio del producto no dependen de la venta. Se van a una tabla propia, y en la tabla de detalle queda solo el identificador del producto.
Paso 3: sacar el cliente de la tabla de ventas (3FN)
El nombre y el teléfono del cliente tampoco dependen de la venta: dependen del cliente. Se van a su propia tabla, y la venta guarda solo el identificador del cliente.
El resultado
Tres tablas, cada una con un tema, unidas por claves foráneas:
CLIENTES PRODUCTOS VENTAS
--------------- --------------- ---------------------
id ← PK id ← PK n_venta ← PK
nombre nombre fecha
telefono precio cliente_id ← FK a CLIENTES
producto_id ← FK a PRODUCTOS
Y ahora, las tres anomalías desaparecieron:
- Se puede cargar un cliente sin inventarle una venta: va a su propia tabla.
- Si Ana cambia de teléfono, se actualiza una sola fila. No hay forma de que quede desactualizado en otro lado.
- Si se anula una venta, se borra una fila de
VENTASy el producto sigue existiendo con su precio.
Se paga un precio: ahora, para ver una venta completa, hay que cruzar tres tablas. Eso se hace con una consulta que combina tablas, y es el motivo por el que a veces conviene no normalizar del todo, como se ve a continuación.
Cuándo conviene desnormalizar
Normalizar tiene un costo, y hay que conocerlo para decidir con criterio. Al repartir los datos en más tablas, cada consulta necesita combinar esas tablas, y eso es más lento que leer una sola. Además, el diseño se vuelve más complejo de entender y de programar.
Por eso existe la desnormalización: volver a duplicar datos a propósito, para ganar velocidad. No es un error de diseño cuando se hace con conocimiento de causa.
| Conviene normalizar cuando… | Puede convenir desnormalizar cuando… |
|---|---|
| Los datos se modifican seguido y hay que mantener la coherencia. | Los datos son casi de solo lectura: se cargan una vez y se consultan miles. |
| El sistema es transaccional: ventas, inscripciones, altas y bajas. | Se trata de un reporte o un tablero que necesita responder rápido. |
| Es la base de datos principal del sistema. | Es una copia preparada para consultas, hecha a partir de la base normalizada. |
Resumen
| Concepto | La idea que hay que recordar |
|---|---|
| Normalizar | Organizar las tablas para que cada dato esté en un solo lugar. |
| Redundancia | El mismo dato repetido. Es el problema que se quiere eliminar. |
| Anomalía de inserción | No se puede cargar un dato sin inventar otro. |
| Anomalía de actualización | Hay que cambiar el mismo dato en varios lugares, y quedan datos contradictorios. |
| Anomalía de borrado | Al borrar una fila se pierde información que no tenía que ver. |
| 1FN | Cada celda tiene un solo valor, y la tabla tiene clave primaria. |
| 2FN | 1FN, y cada campo depende de la clave completa. |
| 3FN | 2FN, y ningún campo depende de otro que no sea la clave. |
| Desnormalizar | Duplicar a propósito para ganar velocidad. Solo con un motivo medido. |