Tecnología que te entiende
Normalización de bases de datos: 1NF, 2NF y 3NF con ejemplos
Bases de datos

Normalización de bases de datos: 1NF, 2NF y 3NF con ejemplos

12 May 2026 3 min de lectura 881 vistas

La normalización es el proceso de organizar una base de datos para eliminar redundancia y dependencias problemáticas. Una tabla mal diseñada puede corromperse sola con el tiempo — la normalización previene eso con reglas matemáticas concretas.

El problema sin normalización

Imagina una tabla que guarda pedidos con toda la información del cliente en cada fila:

| pedido_id | cliente_nombre | cliente_email     | cliente_ciudad | producto      | precio |
|-----------|----------------|-------------------|----------------|---------------|--------|
| 1         | Juan Pérez     | juan@ej.com       | Guadalajara    | Cable HDMI    | 150.00 |
| 2         | Juan Pérez     | juan@ej.com       | Guadalajara    | Mouse USB     | 200.00 |
| 3         | Ana García     | ana@ej.com        | CDMX           | Teclado       | 350.00 |

Problemas evidentes:

  • Anomalía de actualización: Si Juan cambia su email, hay que actualizar múltiples filas
  • Anomalía de inserción: No puedo agregar un cliente sin que tenga un pedido
  • Anomalía de eliminación: Si elimino el único pedido de Ana, pierdo sus datos como cliente
  • Redundancia: El nombre y ciudad de Juan se repite N veces

Primera Forma Normal (1NF)

Regla: cada celda contiene un valor atómico (indivisible) y no hay grupos repetidos.

-- MAL: la columna "telefonos" tiene múltiples valores
| cliente_id | nombre     | telefonos              |
|------------|------------|------------------------|
| 1          | Juan Pérez | 333-1234, 333-5678     |

-- BIEN: tabla separada para teléfonos
CREATE TABLE clientes (
    id INT PRIMARY KEY AUTO_INCREMENT,
    nombre VARCHAR(100) NOT NULL,
    email VARCHAR(150) UNIQUE NOT NULL
);

CREATE TABLE telefonos_clientes (
    id INT PRIMARY KEY AUTO_INCREMENT,
    cliente_id INT NOT NULL,
    telefono VARCHAR(20) NOT NULL,
    tipo ENUM('celular', 'fijo', 'trabajo') DEFAULT 'celular',
    FOREIGN KEY (cliente_id) REFERENCES clientes(id) ON DELETE CASCADE
);

Segunda Forma Normal (2NF)

Regla: debe estar en 1NF y todos los atributos no-clave deben depender de la clave primaria completa (aplica cuando la clave primaria es compuesta).

-- MAL: tabla de inscripciones donde precio_materia depende solo de materia_id
-- (no de la clave compuesta alumno_id + materia_id)
CREATE TABLE inscripciones_mal (
    alumno_id   INT,
    materia_id  INT,
    calificacion DECIMAL(4,2),
    precio_materia DECIMAL(10,2),   -- ← depende solo de materia_id, no del par
    PRIMARY KEY (alumno_id, materia_id)
);

-- BIEN: precio_materia va en su propia tabla
CREATE TABLE materias (
    id     INT PRIMARY KEY AUTO_INCREMENT,
    nombre VARCHAR(100) NOT NULL,
    precio DECIMAL(10,2) NOT NULL
);

CREATE TABLE inscripciones (
    alumno_id   INT,
    materia_id  INT,
    calificacion DECIMAL(4,2),
    PRIMARY KEY (alumno_id, materia_id),
    FOREIGN KEY (alumno_id)  REFERENCES alumnos(id),
    FOREIGN KEY (materia_id) REFERENCES materias(id)
);

Tercera Forma Normal (3NF)

Regla: debe estar en 2NF y ningún atributo no-clave debe depender de otro atributo no-clave (sin dependencias transitivas).

-- MAL: ciudad_cp depende de codigo_postal, no de cliente_id
CREATE TABLE clientes_mal (
    id           INT PRIMARY KEY,
    nombre       VARCHAR(100),
    codigo_postal VARCHAR(10),
    ciudad_cp    VARCHAR(100)    -- ← depende de codigo_postal, no del id
);

-- BIEN: extraer la dependencia transitiva
CREATE TABLE codigos_postales (
    codigo_postal VARCHAR(10) PRIMARY KEY,
    ciudad        VARCHAR(100) NOT NULL,
    estado        VARCHAR(100) NOT NULL
);

CREATE TABLE clientes (
    id           INT PRIMARY KEY AUTO_INCREMENT,
    nombre       VARCHAR(100) NOT NULL,
    codigo_postal VARCHAR(10),
    FOREIGN KEY (codigo_postal) REFERENCES codigos_postales(codigo_postal)
);

¿Cuándo desnormalizar?

La normalización completa puede generar muchos JOINs y afectar el rendimiento en consultas de lectura masiva. A veces se desnormaliza intencionalmente por rendimiento:

  • Reportes y analytics: tablas desnormalizadas (data warehouses)
  • Caché de contadores: guardar el total de vistas en la tabla del artículo en lugar de contar cada vez
  • Datos históricos: guardar el precio al momento de la venta aunque el precio actual cambie
✅ Regla práctica: Diseña normalizado primero (hasta 3NF). Solo desnormaliza cuando tengas evidencia de un problema de rendimiento real, no preventivamente. La prematura optimización es la raíz de muchos diseños complicados innecesariamente.
"Normalizar una base de datos es como ordenar tu código — no es opcional si quieres que el sistema sobreviva al crecimiento."