Una base de datos bien diseñada no solo facilita las consultas, sino que también previene redundancia, errores y problemas de integridad. Aquí entra en juego un concepto clave del diseño relacional: la normalización.
En este artículo exploraremos qué es, por qué es importante y cómo aplicarla paso a paso usando ejemplos prácticos en PostgreSQL.
¿Qué es la normalización en bases de datos?
La normalización es el proceso de organizar los datos dentro de una base de datos para minimizar redundancias y dependencias.
Se logra mediante un conjunto de reglas conocidas como formas normales (NF), que van desde la Primera Forma Normal (1NF) hasta la Quinta Forma Normal (5NF), aunque en la práctica suelen bastar hasta la Tercera Forma Normal (3NF).
¿Por qué es importante normalizar?
Una base de datos no normalizada puede causar:
- Datos duplicados (por ejemplo, registrar varias veces al mismo cliente).
- Actualizaciones inconsistentes (cambiar un dato en un lugar, pero no en otro).
- Eliminación accidental de información (borrar un registro y perder datos relacionados).
La normalización ayuda a que tu base sea más escalable, limpia y segura.
Ejemplo práctico: tabla sin normalizar
Imagina una tabla empleados en su forma inicial, antes de aplicar normalización:
CREATE TABLE empleados_raw (
empleado_id SERIAL PRIMARY KEY,
nombre TEXT,
departamento TEXT,
jefe_departamento TEXT,
proyecto TEXT,
horas_asignadas INT
); Y algunos datos de ejemplo:
INSERT INTO empleados_raw (nombre, departamento, jefe_departamento, proyecto, horas_asignadas) VALUES
('Ana Torres', 'Ventas', 'Carlos Ruiz', 'Proyecto Alfa', 20),
('Luis Pérez', 'Ventas', 'Carlos Ruiz', 'Proyecto Beta', 15),
('Marta Díaz', 'TI', 'Sofía Gómez', 'Proyecto Alfa', 10),
('José López', 'TI', 'Sofía Gómez', 'Proyecto Gamma', 25); Problema: si cambia el jefe de un departamento, debemos actualizarlo en todas las filas. Esto genera redundancia y posibles errores.
Primera Forma Normal (1NF): eliminar datos repetidos y no atómicos
La 1NF exige que cada campo contenga un solo valor y que no existan grupos repetidos.
En este caso, ya la cumplimos: cada celda contiene un valor único.
Segunda Forma Normal (2NF): separar dependencias parciales
En la 2NF, los datos que no dependen completamente de la clave primaria deben moverse a otra tabla.
Creamos tablas separadas para departamentos y proyectos.
CREATE TABLE departamentos (
departamento_id SERIAL PRIMARY KEY,
nombre TEXT,
jefe TEXT
);
CREATE TABLE proyectos (
proyecto_id SERIAL PRIMARY KEY,
nombre TEXT
); Luego, la tabla empleados quedará así:
CREATE TABLE empleados (
empleado_id SERIAL PRIMARY KEY,
nombre TEXT,
departamento_id INT REFERENCES departamentos(departamento_id)
); Y una tabla intermedia para la relación entre empleados y proyectos:
CREATE TABLE empleados_proyectos (
empleado_id INT REFERENCES empleados(empleado_id),
proyecto_id INT REFERENCES proyectos(proyecto_id),
horas_asignadas INT,
PRIMARY KEY (empleado_id, proyecto_id)
); Datos normalizados:
-- Departamentos
INSERT INTO departamentos (nombre, jefe) VALUES
('Ventas', 'Carlos Ruiz'),
('TI', 'Sofía Gómez');
-- Proyectos
INSERT INTO proyectos (nombre) VALUES
('Proyecto Alfa'),
('Proyecto Beta'),
('Proyecto Gamma');
-- Empleados
INSERT INTO empleados (nombre, departamento_id) VALUES
('Ana Torres', 1), -- Ventas
('Luis Pérez', 1), -- Ventas
('Marta Díaz', 2), -- TI
('José López', 2); -- TI
-- Relación empleados - proyectos
INSERT INTO empleados_proyectos (empleado_id, proyecto_id, horas_asignadas) VALUES
(1, 1, 20), -- Ana Torres -> Proyecto Alfa
(2, 2, 15), -- Luis Pérez -> Proyecto Beta
(3, 1, 10), -- Marta Díaz -> Proyecto Alfa
(4, 3, 25); -- José López -> Proyecto Gamma Tercera Forma Normal (3NF): eliminar dependencias transitivas
La 3NF elimina campos que dependen de otros campos que no son clave.
En este caso, jefe depende del departamento, no del empleado.
Ya lo solucionamos al mover jefe a la tabla departamentos.
Resultado:
Cada tabla tiene un propósito claro:
empleados: almacena solo empleados.departamentos: almacena departamentos y sus jefes.proyectos: almacena proyectos.empleados_proyectos: asocia empleados con proyectos.
Cómo probarlo en db-fiddle.com
Puedes copiar los scripts anteriores y ejecutarlos directamente en db-fiddle.com seleccionando PostgreSQL 16.
Allí podrás realizar consultas como:
SELECT e.nombre AS empleado, d.nombre AS departamento, p.nombre AS proyecto, ep.horas_asignadas
FROM empleados e
JOIN departamentos d ON e.departamento_id = d.departamento_id
JOIN empleados_proyectos ep ON e.empleado_id = ep.empleado_id
JOIN proyectos p ON ep.proyecto_id = p.proyecto_id; Buenas prácticas en el diseño eficiente
- Normaliza hasta la 3NF en la mayoría de los casos.
- Desnormaliza estratégicamente cuando necesites velocidad (por ejemplo, en análisis de datos).
- Define claves primarias y foráneas con sentido lógico.
- Documenta las relaciones entre tablas.
Conclusión
La normalización es una de las herramientas importantes del diseño relacional.
Aplicarla correctamente te asegura bases de datos estables, limpias y escalables.