Curso de MySQL

Normalización de bases de datos: las formas normales explicadas

Por Víctor Peña · Publicado el

Hola, ¿cómo están? Última lección del curso de MySQL. Cerramos volviendo al principio: el diseño.

La normalización es el conjunto de reglas que convierte un montón de datos en una base bien estructurada. Suena académico, pero es lo que decide si tu sistema va a ser mantenible o un problema permanente.

¡Empecemos!

Qué es la normalización

Es un proceso para organizar los datos de forma que se elimine la redundancia y se mantenga la coherencia.

Consiste en aplicar una serie de reglas llamadas formas normales. Cada una resuelve un tipo de problema, y se aplican en orden: para estar en la segunda hay que cumplir la primera.

En la práctica, con llegar a la tercera forma normal cubres el 95 % de los casos.

El problema que resuelve

Partamos de una tabla mal diseñada, que es como se entiende mejor:

id paciente telefonos doctor especialidad fecha costo
1 Ana Torres 769805, 712233 Carlos Mendoza Cardiología 2026-04-10 250
2 Ana Torres 769805, 712233 Carlos Mendoza Cardiología 2026-04-20 250
3 Luis Gomez 776644 Jorge Rojas Traumatología 2026-04-11 300

Los problemas, que tienen nombre propio:

Anomalía de actualización. Si Ana cambia de teléfono, hay que modificarlo en todas sus filas. Si olvidas una, tienes dos versiones de la verdad.

Anomalía de inserción. No puedes registrar una especialidad nueva hasta que exista una cita con ella.

Anomalía de eliminación. Si borras la cita 3, pierdes también los datos de Luis y de la especialidad de traumatología.

Y algo más sutil: nada garantiza la consistencia. «Cardiología» en una fila y «cardiologia» en otra son dos cosas distintas para la base de datos.

Primera forma normal (1FN)

Cada campo contiene un solo valor, y no hay grupos repetidos.

El problema en nuestra tabla es la columna telefonos: guarda dos números separados por coma.

Eso rompe todo. No puedes buscar por teléfono con precisión, no puedes contarlos, y añadir un tercero significa manipular texto.

La solución: una tabla aparte.

CREATE TABLE telefonos (
    id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    paciente_id INT UNSIGNED NOT NULL,
    numero VARCHAR(20) NOT NULL,
    tipo ENUM('celular','fijo','trabajo') DEFAULT 'celular',
    FOREIGN KEY (paciente_id) REFERENCES pacientes(id)
);

La señal de alarma de la 1FN: columnas con valores separados por comas, o columnas numeradas como telefono1, telefono2, telefono3.

Ese segundo caso es igual de problemático: ¿qué haces cuando alguien tiene cuatro teléfonos? ¿Y cómo buscas en las tres columnas a la vez?

Segunda forma normal (2FN)

Cumple 1FN, y cada campo depende de la clave primaria completa.

Esta solo aplica cuando la clave primaria es compuesta. Veámoslo con la tabla intermedia de estudios:

CREATE TABLE cita_estudio (
    cita_id INT,
    estudio_id INT,
    resultado TEXT,
    nombre_estudio VARCHAR(100),   -- ← problema
    precio_estudio DECIMAL(10,2),  -- ← problema
    PRIMARY KEY (cita_id, estudio_id)
);

resultado depende de la combinación completa: es el resultado de ese estudio en esa cita. Correcto.

Pero nombre_estudio y precio_estudio dependen solo de estudio_id, no de la cita. Están repetidos en cada fila donde aparece ese estudio.

La solución: llevarlos a la tabla estudios, donde pertenecen.

CREATE TABLE cita_estudio (
    cita_id INT,
    estudio_id INT,
    resultado TEXT,
    PRIMARY KEY (cita_id, estudio_id)
);

Tercera forma normal (3FN)

Cumple 2FN, y ningún campo depende de otro que no sea la clave.

Es la más frecuente y la que más se viola. Mira esta tabla:

id matricula nombre especialidad_id especialidad_nombre
1 MED-001 Carlos Mendoza 1 Cardiología
2 MED-002 Laura Vargas 2 Pediatría

especialidad_nombre no depende del doctor: depende de especialidad_id. Es una dependencia transitiva, y trae los mismos problemas de siempre: si se corrige el nombre de la especialidad hay que actualizarlo en todos los doctores.

La solución: dejar solo la clave foránea y recuperar el nombre con un JOIN.

La señal de alarma de la 3FN: dos columnas donde una es el id de algo y la otra su descripción.

Nuestro sistema, normalizado

El diseño que hemos usado durante el curso cumple la 3FN:

especialidades (id, nombre, descripcion)

doctores (id, matricula, nombre, apellido, especialidad_id)

citas (id, paciente_id, doctor_id, fecha, hora, costo, estado)

pacientes (id, cedula, nombre, apellido, fecha_nacimiento)

Cada dato vive en un solo lugar. Cambiar el nombre de una especialidad es un UPDATE sobre una fila.

Un método práctico

No hace falta memorizar las definiciones formales. En la práctica, revisa tu diseño con estas tres preguntas:

  1. ¿Hay algún campo con varios valores dentro? → falta 1FN.
  2. ¿Algún dato se repite igual en muchas filas? → probablemente falta 2FN o 3FN.
  3. ¿Hay un id y su descripción en la misma tabla? → falta 3FN.

Si las tres respuestas son «no», tu diseño está bien para casi cualquier proyecto.

Las formas normales superiores

Existen la cuarta, la quinta y la forma normal de Boyce-Codd. Resuelven casos bastante específicos y rara vez aparecen en aplicaciones normales.

Menciono la de Boyce-Codd porque es la más citada: es una versión más estricta de la 3FN para tablas con varias claves candidatas. Si tu diseño ya está en 3FN y no tiene claves candidatas solapadas, seguramente también la cumple.

Con 3FN vas bien servido.

Desnormalizar a propósito

Y ahora la otra cara, porque normalizar no siempre es la respuesta final.

La normalización optimiza la escritura y la coherencia: cada dato en un solo sitio. Pero eso significa más JOIN al consultar.

En sistemas con mucha lectura, a veces se duplica un dato deliberadamente:

-- Guardar el total ya calculado en lugar de sumar las líneas cada vez
ALTER TABLE facturas ADD COLUMN total DECIMAL(12,2);

-- Guardar el nombre del cliente junto al pedido
ALTER TABLE pedidos ADD COLUMN cliente_nombre VARCHAR(200);

Cuándo se justifica:

  • La consulta se ejecuta miles de veces al día y el JOIN la ralentiza de forma medible.
  • El dato duplicado casi no cambia.
  • Tienes forma de mantenerlo sincronizado, por ejemplo con un trigger.

El costo: ahora tienes el mismo dato en dos sitios, y mantenerlos coherentes es responsabilidad tuya. Si se desincronizan, tienes dos versiones de la verdad y ningún aviso.

Un caso especial y muy común: en una factura conviene guardar el precio del producto en el momento de la venta. No es desnormalización mal hecha, es información distinta: el precio actual del catálogo y el precio al que se vendió son dos datos diferentes, y confundirlos es un error de diseño más grave.

La regla: normaliza por defecto, desnormaliza cuando midas que hace falta. Nunca al revés.

Errores comunes

  • Campos con listas separadas por comas.
  • Columnas numeradas: telefono1, telefono2.
  • Guardar el id y la descripción en la misma tabla.
  • Desnormalizar antes de medir, por suponer que los JOIN son lentos.
  • Normalizar en exceso, partiendo en cinco tablas algo que funcionaba bien en dos.
  • Guardar datos calculables, como la edad o un total que se puede sumar.

Para cerrar el curso

La normalización no es teoría académica: es lo que evita que dentro de dos años tengas tres versiones del teléfono de un cliente y nadie sepa cuál es la buena.

Con esto cerramos el curso de MySQL. Empezamos por qué es una base de datos relacional, diseñamos con un diagrama entidad-relación, creamos tablas y relaciones, insertamos y consultamos datos, aprendimos a unir tablas y agrupar, y terminamos optimizando y protegiendo lo construido.

Si tuviera que resumir el curso en cinco reglas:

  1. Diseña antes de crear. Un diagrama en papel cuesta un borrón; cambiar la estructura en producción cuesta semanas.
  2. DECIMAL para dinero, fechas como fecha, NOT NULL en lo obligatorio.
  3. WHERE antes que nada en cualquier UPDATE o DELETE.
  4. Indexa lo que consultas mucho, no todo por si acaso.
  5. Respaldos automáticos, y prueba la restauración.

El siguiente paso natural es conectar todo esto con un lenguaje. Si programas en PHP, lo vimos en uso de bases de datos con PHP; y si quieres dar el salto a un framework, Laravel construye sobre exactamente estos conceptos.

Saludos y éxitos.

Norvic Software

Desarrollamos el software que tu empresa necesita

Somos una fábrica de software en Bolivia. Construimos sistemas a medida y aplicaciones móviles, y llevamos Inteligencia Artificial a las empresas que ya tienen un sistema funcionando.

Solicitar cotizaciónVer todos los servicios

Cotización sin costo · Respuesta directa por WhatsApp