De los Planos a la Realidad

DDL, Diccionario de Datos e Inserción · Semana 6 · Unidad II

Universidad San Sebastián

2026-01-01

¿Dónde Estamos?

  • W04: Diseñamos el MER de TechStyle y normalizamos hasta 3FN.
  • W05: Ampliamos el modelo (Proveedores, Despachos, Devoluciones), aprendimos MySQL Workbench y generamos el script DDL.
  • Hoy (W06): Ejecutamos ese script — la base de datos pasa de plano a sistema real — y cargamos los primeros datos.

El entregable de hoy: una base de datos funcional en MySQL con datos reales de TechStyle.

El Problema de Roberto Esta Semana

El directorio de TechStyle aprobó el modelo diseñado en W05. Roberto convoca a Juan, el analista de datos:

  • Roberto: “El modelo está aprobado. Necesito la base de datos funcionando para el lunes. El equipo de ventas quiere ingresar los primeros registros.”
  • María: “¿Cuándo puedo hacer mi primera consulta real? Necesito ver las ventas del trimestre.”
  • Carlos: “¿Cómo me aseguro de que si falla la carga de datos a mitad de camino, no queden registros a medias?”

Dos tareas para Juan hoy: crear la base de datos y cargar los datos iniciales. La pregunta de Carlos la responderemos en W07.

De los Planos a la Construcción

En W05, Juan entregó un plano arquitectónico. Ahora toca construir.

Etapa Analogía Herramienta SQL
Diseño del modelo Plano arquitectónico MER + MySQL Workbench
Crear la estructura Construir los muros CREATE TABLE (DDL)
Ingresar datos Amueblar las habitaciones INSERT INTO (DML)
Operaciones seguras Seguros contra incendio Transacciones (W07)

DDL (Data Definition Language): define la estructura de la base de datos. DML (Data Manipulation Language): manipula los datos dentro de esa estructura.

Arquitectura de MySQL: ¿Qué Hay Dentro?

graph TD
    A["MySQL Server"] --> B["Base de Datos: techstyle"]
    B --> C["Tabla: clientes"]
    B --> D["Tabla: productos"]
    B --> E["Tabla: ventas"]
    B --> F["Tabla: detalle_venta"]
    B --> G["... (9 tablas en total)"]
    style A fill:#e3f2fd,stroke:#1565c0
    style B fill:#fff3e0,stroke:#e65100

Un servidor MySQL puede contener múltiples bases de datos. Una base de datos contiene múltiples tablas. Juan creará la base de datos techstyle y luego todas sus tablas dentro de ella.

Paso 1: Crear la Base de Datos

-- Crear la base de datos
CREATE DATABASE IF NOT EXISTS techstyle
    CHARACTER SET utf8mb4
    COLLATE utf8mb4_spanish_ci;

-- Seleccionar la base de datos activa
USE techstyle;

IF NOT EXISTS: evita error si ya existe. Útil para re-ejecutar el script sin problemas.

CHARACTER SET utf8mb4: soporta todos los caracteres del español (ñ, tildes) y emojis.

COLLATE utf8mb4_spanish_ci: las comparaciones de texto respetan el orden del alfabeto español (ci = case-insensitive: ‘Juan’ = ‘juan’).

El Diccionario de Datos: La Guía de Construcción

El Diccionario de Datos especifica, tabla por tabla, cada columna con su tipo, restricciones y descripción.

Tabla CLIENTES — Diccionario de Datos:

Columna Tipo NOT NULL Restricción Descripción
cliente_id INT PK, AUTO_INCREMENT Identificador único del cliente
nombre VARCHAR(50) Nombre de pila
apellido VARCHAR(50) Apellido paterno
email VARCHAR(100) UNIQUE Correo único por cliente
region VARCHAR(50) Región de Chile del cliente
segmento VARCHAR(20) No CHECK: Premium/Estándar/Básico Segmento comercial
fecha_registro DATE Fecha de alta en el sistema

El Diccionario de Datos: Tabla PRODUCTOS

Columna Tipo NOT NULL Restricción Descripción
producto_id INT PK, AUTO_INCREMENT Identificador único del producto
nombre_producto VARCHAR(100) Nombre comercial del producto
categoria_id INT FK → CATEGORIAS Categoría a la que pertenece
precio_venta DECIMAL(10,2) CHECK > 0 Precio de venta al público
costo_unitario DECIMAL(10,2) No CHECK > 0 Costo de adquisición
stock INT DEFAULT 0, CHECK ≥ 0 Unidades disponibles en bodega

DECIMAL(10,2): hasta 10 dígitos en total, 2 decimales. Ejemplo: 89990.00. Se usa para dinero porque evita errores de redondeo que FLOAT puede introducir.

Paso 2: Crear las Tablas (Orden Importa)

Las tablas se crean de padre a hijo: primero las que no tienen FK, luego las que referencian a otras.

-- 1° CATEGORIAS (sin FK externa)
CREATE TABLE categorias (
    categoria_id       INT          NOT NULL AUTO_INCREMENT,
    nombre_categoria   VARCHAR(50)  NOT NULL,
    categoria_padre_id INT          NULL,
    PRIMARY KEY (categoria_id),
    FOREIGN KEY (categoria_padre_id)
        REFERENCES categorias(categoria_id)
        ON DELETE RESTRICT
        ON UPDATE CASCADE
);

-- 2° CLIENTES (sin FK)
CREATE TABLE clientes (
    cliente_id      INT          NOT NULL AUTO_INCREMENT,
    nombre          VARCHAR(50)  NOT NULL,
    apellido        VARCHAR(50)  NOT NULL,
    email           VARCHAR(100) NOT NULL,
    region          VARCHAR(50)  NOT NULL,
    segmento        VARCHAR(20)  NULL
        CHECK (segmento IN ('Premium', 'Estándar', 'Básico')),
    fecha_registro  DATE         NOT NULL,
    PRIMARY KEY (cliente_id),
    UNIQUE (email)
);

Paso 2: Tablas con Claves Foráneas

-- 3° PRODUCTOS (FK → CATEGORIAS)
CREATE TABLE productos (
    producto_id      INT           NOT NULL AUTO_INCREMENT,
    nombre_producto  VARCHAR(100)  NOT NULL,
    categoria_id     INT           NOT NULL,
    precio_venta     DECIMAL(10,2) NOT NULL CHECK (precio_venta > 0),
    costo_unitario   DECIMAL(10,2) NULL     CHECK (costo_unitario > 0),
    stock            INT           NOT NULL DEFAULT 0
        CHECK (stock >= 0),
    PRIMARY KEY (producto_id),
    FOREIGN KEY (categoria_id)
        REFERENCES categorias(categoria_id)
        ON DELETE RESTRICT
        ON UPDATE CASCADE
);

-- 4° VENTAS (FK → CLIENTES)
CREATE TABLE ventas (
    venta_id    INT  NOT NULL AUTO_INCREMENT,
    fecha       DATE NOT NULL,
    cliente_id  INT  NOT NULL,
    PRIMARY KEY (venta_id),
    FOREIGN KEY (cliente_id)
        REFERENCES clientes(cliente_id)
        ON DELETE RESTRICT
        ON UPDATE CASCADE
);

Paso 2: Tabla de Detalle (Clave Compuesta)

-- 5° DETALLE_VENTA (FK → VENTAS y PRODUCTOS)
CREATE TABLE detalle_venta (
    venta_id        INT           NOT NULL,
    producto_id     INT           NOT NULL,
    cantidad        INT           NOT NULL CHECK (cantidad > 0),
    precio_unitario DECIMAL(10,2) NOT NULL CHECK (precio_unitario > 0),
    descuento_pct   DECIMAL(5,2)  NOT NULL DEFAULT 0.00
        CHECK (descuento_pct BETWEEN 0 AND 100),
    PRIMARY KEY (venta_id, producto_id),
    FOREIGN KEY (venta_id)
        REFERENCES ventas(venta_id)
        ON DELETE CASCADE
        ON UPDATE CASCADE,
    FOREIGN KEY (producto_id)
        REFERENCES productos(producto_id)
        ON DELETE RESTRICT
        ON UPDATE CASCADE
);

ON DELETE CASCADE en detalle_venta: si se elimina una venta (ej. cancelación), sus líneas de detalle se eliminan automáticamente. Tiene sentido: no existen líneas sin venta padre.

🚀 Desafío Rápido 1

Analiza el siguiente fragmento del script de TechStyle:

CREATE TABLE despachos (
    despacho_id        INT          NOT NULL AUTO_INCREMENT,
    venta_id           INT          NOT NULL,
    direccion_entrega  VARCHAR(200) NOT NULL,
    fecha_despacho     DATE         NOT NULL,
    fecha_entrega_est  DATE         NULL,
    estado             VARCHAR(20)  NOT NULL DEFAULT 'Pendiente',
    PRIMARY KEY (despacho_id),
    FOREIGN KEY (venta_id)
        REFERENCES ventas(venta_id)
        ON DELETE RESTRICT
);
  1. ¿Por qué fecha_entrega_est permite NULL pero fecha_despacho no?
  2. ¿Qué pasa si intentas insertar un despacho con venta_id = 999 y esa venta no existe?
  3. Agrega una restricción CHECK para que estado solo acepte los valores válidos del negocio.

Paso 3: Insertar Datos con INSERT INTO

Una vez creada la estructura, hay que poblar las tablas. La sentencia INSERT INTO agrega nuevas filas.

-- Sintaxis básica: se especifican columnas y valores
INSERT INTO clientes (nombre, apellido, email, region, segmento, fecha_registro)
VALUES ('Juan', 'Pérez', 'juan.perez@mail.com', 'Metropolitana', 'Premium', '2024-03-15');

-- MySQL asigna cliente_id = 1 automáticamente (AUTO_INCREMENT)

Buena práctica: siempre listar explícitamente las columnas. Si en el futuro se agrega una columna a la tabla, un INSERT sin lista de columnas fallará porque el número de valores ya no coincide.

INSERT de Múltiples Filas

-- Insertar múltiples clientes en una sola sentencia (más eficiente)
INSERT INTO clientes (nombre, apellido, email, region, segmento, fecha_registro)
VALUES
    ('María',   'López',    'maria.lopez@mail.com',    'Valparaíso',    'Estándar', '2024-04-02'),
    ('Carlos',  'Muñoz',    'carlos.munoz@mail.com',   'Biobío',        'Básico',   '2024-05-18'),
    ('Sofía',   'Ramírez',  'sofia.ramirez@mail.com',  'Metropolitana', 'Premium',  '2024-06-30'),
    ('Diego',   'Torres',   'diego.torres@mail.com',   'Araucanía',     'Estándar', '2024-07-11');

Insertar con relaciones:

-- Primero la categoría padre
INSERT INTO categorias (nombre_categoria, categoria_padre_id)
VALUES ('Ropa', NULL);  -- categoria_id = 1

-- Luego las subcategorías (referencian el id 1)
INSERT INTO categorias (nombre_categoria, categoria_padre_id)
VALUES ('Poleras', 1), ('Pantalones', 1), ('Chaquetas', 1);

El Orden de INSERT También Importa

Al igual que con CREATE TABLE, los datos deben insertarse respetando las relaciones.

  1. Insertar CATEGORIAS antes que PRODUCTOS.
  2. Insertar CLIENTES antes que VENTAS.
  3. Insertar PRODUCTOS antes que DETALLE_VENTA.
  4. Insertar VENTAS antes que DETALLE_VENTA y DESPACHOS.

¿Qué pasa si Juan intenta insertar una venta antes de insertar el cliente?

ERROR 1452: Cannot add or update a child row:
a foreign key constraint fails
(`techstyle`.`ventas`, CONSTRAINT `ventas_ibfk_1`
FOREIGN KEY (`cliente_id`) REFERENCES `clientes` (`cliente_id`))

MySQL protege la integridad — no permite datos huérfanos.

🚀 Desafío Rápido 2

TechStyle tiene este producto: Nike Air Max 2026, categoría Calzado (categoria_id = 5), precio venta $89.990, costo unitario $45.000, stock 150 unidades.

  1. Escribe el INSERT INTO correcto para agregar este producto.
  2. Juan intenta insertar el mismo email de un cliente ya registrado. ¿Qué error recibe y por qué?
  3. ¿Qué diferencia hay entre omitir una columna en el INSERT vs. poner NULL explícitamente?

Puntos Clave de la Semana 6

  • DDL vs DML: CREATE TABLE define la estructura; INSERT INTO agrega los datos. El orden de ejecución en ambos casos sigue la jerarquía de FK (tablas padre antes que tablas hijo).
  • El Diccionario de Datos especifica tipo, restricciones y significado de cada columna — es el contrato entre el analista y la base de datos.
  • Los tipos de datos (VARCHAR, INT, DECIMAL, DATE) y las restricciones (NOT NULL, UNIQUE, CHECK) son la implementación técnica de las reglas del negocio.
  • AUTO_INCREMENT genera identificadores únicos automáticamente; nunca se incluye en el INSERT INTO.
  • Insertar datos con FK exige respetar el orden: primero los registros padre, luego los registros hijo.

Preview del Laboratorio W06

Lab W06: Creando e Insertando Datos en TechStyle

  • Ejecutarás el script DDL completo generado en W05 para crear las 9 tablas de TechStyle en MySQL.
  • Cargarás los primeros datos mediante sentencias INSERT INTO respetando el orden de claves foráneas.
  • Verificarás la estructura creada con SHOW TABLES y DESCRIBE.
  • Al finalizar, tendrás la base de datos de TechStyle con estructura completa y datos iniciales listos.

En W07 aprenderemos a garantizar que operaciones compuestas — como registrar una venta con múltiples productos — sean completamente seguras ante fallas del sistema.