SQL y Bases de DatosDiseño y OptimizaciónLección 11 de 20
Normalización de Base de Datos
La normalización es el proceso de diseñar tablas para eliminar redundancia. Sin normalización, los mismos datos aparecen en múltiples lugares: si un cliente cambia su dirección, habría que actualizarla en decenas de filas. Con normalización, cada dato existe en un solo lugar y se referencia desde otros.
Las tres formas normales básicas: 1FN (cada celda tiene un solo valor atómico, sin listas), 2FN (cada columna depende de toda la clave primaria, no solo parte de ella), 3FN (las columnas no dependen entre sí, solo de la clave primaria). En la práctica, llegar a 3FN es suficiente para la mayoría de los sistemas.
-- PROBLEMA: tabla de ventas sin normalizar
-- ventas_mal: id, cliente, email_cliente, telefono_cliente,
-- producto1, precio1, producto2, precio2, ciudad_cliente
-- 1FN: Primera Forma Normal
-- REGLA: sin grupos repetidos, cada celda un solo valor
-- Problema: producto1, producto2 son grupos repetidos
-- Solución: tabla separada para los items
-- 2FN: Segunda Forma Normal (requiere 1FN)
-- REGLA: cada columna depende de la PK completa
-- Solo aplica a tablas con PK compuesta
-- Problema: si PK es (venta_id, producto_id),
-- el nombre del producto depende solo de producto_id
-- Solución: separar productos en su propia tabla
-- 3FN: Tercera Forma Normal (requiere 2FN)
-- REGLA: sin dependencias transitivas
-- Problema: ciudad → codigo_postal → region
-- el region depende de codigo_postal, no del cliente directamente
-- Solución: tabla de codigos_postales separada
-- Diseño NORMALIZADO (3FN) del ejemplo de ventas:
CREATE TABLE clientes (
id SERIAL PRIMARY KEY,
nombre VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
telefono VARCHAR(20)
);
CREATE TABLE productos (
id SERIAL PRIMARY KEY,
nombre VARCHAR(200) NOT NULL,
precio DECIMAL(10, 2) NOT NULL,
categoria VARCHAR(100)
);
CREATE TABLE ventas (
id SERIAL PRIMARY KEY,
cliente_id INTEGER NOT NULL REFERENCES clientes(id),
fecha TIMESTAMP DEFAULT NOW()
);
CREATE TABLE venta_items (
id SERIAL PRIMARY KEY,
venta_id INTEGER NOT NULL REFERENCES ventas(id),
producto_id INTEGER NOT NULL REFERENCES productos(id),
cantidad INTEGER NOT NULL CHECK (cantidad > 0),
precio_venta DECIMAL(10, 2) NOT NULL -- precio al momento de vender
);
-- Ventaja: si el precio del producto cambia, las ventas antiguas conservan
-- el precio correcto gracias a precio_venta.
ConsejoDesnormalizar es a veces válido para mejorar el rendimiento de lectura (caches, reportes). Por ejemplo, guardar el total de un pedido aunque se pueda calcular desde sus items evita recalcular en cada consulta. Normaliza primero, desnormaliza cuando los benchmarks lo justifiquen.
Practica esta lección
Resuelve los ejercicios del curso de SQL y Bases de Datos en la app, gratis y con corrección automática.
Empezar a practicar