FullStackJS Camp
Módulo 5·practica·4h
Objetivos de aprendizaje
  • Modificar tablas existentes con ALTER TABLE.
  • Agregar y eliminar columnas y constraints.
  • Distinguir DROP TABLE de TRUNCATE TABLE.
  • Crear índices para mejorar el rendimiento de consultas.
  • Configurar integridad referencial: ON DELETE y ON UPDATE CASCADE.

Definición de Tablas DDL (Parte II)

En esta segunda parte de DDL cubrimos cómo modificar esquemas existentes (algo que ocurre constantemente en proyectos reales), gestionar índices y configurar el comportamiento de las claves foráneas.


ALTER TABLE — Modificar tablas

ALTER TABLE permite cambiar la estructura de una tabla sin recrearla (y sin perder los datos existentes).

Agregar columna

sql
-- Agregar una columna al final
ALTER TABLE usuarios
  ADD COLUMN telefono VARCHAR(20) NULL;

-- Agregar en una posición específica
ALTER TABLE usuarios
  ADD COLUMN activo TINYINT(1) NOT NULL DEFAULT 1 AFTER correo;

-- Agregar al inicio
ALTER TABLE usuarios
  ADD COLUMN uuid CHAR(36) NULL FIRST;

Eliminar columna

sql
-- Primero verificar: ¿qué contiene esa columna?
SELECT telefono FROM usuarios LIMIT 5;

-- Eliminar
ALTER TABLE usuarios DROP COLUMN telefono;

Modificar columna

sql
-- Cambiar el tipo o las restricciones de una columna
ALTER TABLE usuarios
  MODIFY COLUMN nombre VARCHAR(120) NOT NULL;  -- ampliar de 80 a 120

-- Renombrar columna (MySQL 8.0+)
ALTER TABLE usuarios
  RENAME COLUMN contrasena TO password_hash;

-- Cambiar tipo Y nombre en un solo paso (CHANGE)
ALTER TABLE usuarios
  CHANGE contrasena password_hash VARCHAR(255) NOT NULL;

Agregar constraint

sql
-- Agregar UNIQUE
ALTER TABLE usuarios
  ADD CONSTRAINT uq_telefono UNIQUE (telefono);

-- Agregar INDEX
ALTER TABLE transacciones
  ADD INDEX idx_fecha (transaction_date);

-- Agregar FOREIGN KEY
ALTER TABLE transacciones
  ADD CONSTRAINT fk_currency
    FOREIGN KEY (currency_id) REFERENCES monedas(currency_id)
    ON DELETE RESTRICT
    ON UPDATE CASCADE;

Eliminar constraint

sql
-- Eliminar FOREIGN KEY (primero hay que saber su nombre)
SHOW CREATE TABLE transacciones;  -- busca el nombre del CONSTRAINT

ALTER TABLE transacciones
  DROP FOREIGN KEY fk_trans_sender;

-- Eliminar UNIQUE o INDEX
ALTER TABLE usuarios
  DROP INDEX uq_telefono;

-- Eliminar PRIMARY KEY (cuidado: solo si no tiene FK que la referencien)
ALTER TABLE tabla_temp
  DROP PRIMARY KEY;

Múltiples cambios en una sola sentencia

sql
-- Más eficiente que varios ALTER TABLE separados
ALTER TABLE usuarios
  ADD COLUMN telefono    VARCHAR(20)   NULL,
  ADD COLUMN updated_at  DATETIME      NULL DEFAULT CURRENT_TIMESTAMP
                                       ON UPDATE CURRENT_TIMESTAMP,
  MODIFY COLUMN nombre   VARCHAR(120)  NOT NULL,
  ADD INDEX idx_nombre   (nombre);

RENAME TABLE

sql
-- Renombrar una tabla
RENAME TABLE usuarios TO users;

-- Renombrar múltiples tablas en una operación atómica
RENAME TABLE
  usuarios     TO users,
  transacciones TO transactions;

DROP TABLE — Eliminar tablas

sql
-- Eliminar una tabla (estructura + todos los datos)
DROP TABLE IF EXISTS tabla_temp;

-- Eliminar múltiples tablas
DROP TABLE IF EXISTS tabla_a, tabla_b;

TRUNCATE TABLE — Vaciar tablas

sql
-- Elimina TODAS las filas y resetea AUTO_INCREMENT
TRUNCATE TABLE transacciones;

DROP TABLE vs TRUNCATE TABLE vs DELETE

DROP TABLETRUNCATE TABLEDELETE FROM
Elimina estructura
Elimina datos✅ (todas)✅ (con WHERE)
Resetea AUTO_INCREMENT
Puede hacer ROLLBACK❌ en MySQL
Respeta FK❌ (con checks off)
VelocidadMuy rápidoMuy rápidoLento en tablas grandes

Índices (INDEX)

Los índices aceleran las consultas SELECT al crear una estructura auxiliar que MySQL puede recorrer más rápido (similar al índice de un libro).

Cuándo crear un índice

sql
-- Columnas frecuentes en WHERE
ALTER TABLE transacciones
  ADD INDEX idx_sender (sender_user_id);

-- Columnas frecuentes en JOIN
ALTER TABLE transacciones
  ADD INDEX idx_receiver (receiver_user_id);

-- Columnas frecuentes en ORDER BY o GROUP BY
ALTER TABLE transacciones
  ADD INDEX idx_fecha (transaction_date);

-- Índice compuesto (útil para WHERE con múltiples condiciones)
ALTER TABLE transacciones
  ADD INDEX idx_sender_fecha (sender_user_id, transaction_date);

Ver índices existentes

sql
SHOW INDEX FROM transacciones;

Eliminar índice

sql
ALTER TABLE transacciones
  DROP INDEX idx_fecha;

Cuándo NO crear índices

  • Tablas muy pequeñas (menos de unos pocos miles de filas) — el overhead supera el beneficio
  • Columnas que se actualizan muy frecuentemente — el índice debe actualizarse en cada UPDATE/INSERT
  • Columnas con muy poca variedad de valores (ej: activo TINYINT(1)) — poco beneficio

Integridad referencial: ON DELETE y ON UPDATE

Al definir una FOREIGN KEY puedes especificar qué pasa cuando se borra o modifica la fila referenciada:

AcciónComportamiento
RESTRICT (por defecto)Impide el DELETE/UPDATE si hay filas hijas
CASCADEPropaga el DELETE/UPDATE a las filas hijas automáticamente
SET NULLPone NULL en la FK de las filas hijas
NO ACTIONSimilar a RESTRICT en MySQL
sql
-- CASCADE: si se borra un usuario, se borran sus transacciones automáticamente
CREATE TABLE transacciones (
  transaction_id   INT           AUTO_INCREMENT,
  sender_user_id   INT           NOT NULL,
  receiver_user_id INT           NOT NULL,
  valor            DECIMAL(12,2) NOT NULL,
  transaction_date DATETIME      NOT NULL DEFAULT CURRENT_TIMESTAMP,

  PRIMARY KEY (transaction_id),

  CONSTRAINT fk_trans_sender
    FOREIGN KEY (sender_user_id)
    REFERENCES usuarios(user_id)
    ON DELETE CASCADE
    ON UPDATE CASCADE,

  CONSTRAINT fk_trans_receiver
    FOREIGN KEY (receiver_user_id)
    REFERENCES usuarios(user_id)
    ON DELETE CASCADE
    ON UPDATE CASCADE
);

Buenas prácticas de esquema

sql
-- ✅ 1. Nombres consistentes: snake_case, singular o plural consistente
CREATE TABLE user_accounts (...);  -- o usuarios, no mezclar

-- ✅ 2. Siempre PRIMARY KEY en cada tabla
-- ✅ 3. Declara NOT NULL en columnas obligatorias
-- ✅ 4. Usa DEFAULT para valores comunes (fechas, estados, flags)
-- ✅ 5. Nombra los constraints explícitamente
CONSTRAINT fk_trans_sender FOREIGN KEY ...

-- ✅ 6. Índices en columnas usadas en JOIN y WHERE frecuentes
-- ✅ 7. Usa DECIMAL para dinero, nunca FLOAT
-- ✅ 8. VARCHAR para texto variable, CHAR para longitud fija conocida

-- ❌ Evitar: tablas sin PK
-- ❌ Evitar: usar TEXT cuando VARCHAR es suficiente
-- ❌ Evitar: FK sin índice en la columna hija (ralentiza las consultas)