ALTER TABLE

La sentencia ALTER TABLE modifica la estructura de una tabla existente. Permite añadir, modificar o eliminar columnas, crear o eliminar índices y restricciones, renombrar la tabla, y cambiar sus opciones. Es la herramienta fundamental para evolucionar el esquema de la base de datos sin tener que recrear las tablas desde cero.

Sintaxis general

ALTER TABLE nombre_tabla
    accion1,
    accion2,
    ...;

Puedes combinar múltiples acciones en una sola sentencia ALTER TABLE, separándolas por comas. MySQL las ejecuta todas en una única operación, lo que es más eficiente que ejecutar varias sentencias separadas.

Tabla de ejemplo

Para los ejemplos de este artículo, creamos una tabla de prueba:

CREATE TABLE empleados_demo (
    id INT AUTO_INCREMENT PRIMARY KEY,
    nombre VARCHAR(50) NOT NULL,
    email VARCHAR(100),
    salario DECIMAL(8, 2)
);
 
INSERT INTO empleados_demo (nombre, email, salario) VALUES
('Ana', 'ana@empresa.com', 35000.00),
('Luis', 'luis@empresa.com', 42000.00),
('Eva', 'eva@empresa.com', 38000.00);

Añadir una columna

ALTER TABLE empleados_demo
    ADD COLUMN departamento VARCHAR(50) DEFAULT 'General';
Query OK, 0 rows affected (0.05 sec)
Records: 0  Duplicates: 0  Warnings: 0

La nueva columna se añade al final de la tabla. Todas las filas existentes reciben el valor por defecto ('General' en este caso, o NULL si no se especifica valor por defecto).

Para verificar:

SELECT * FROM empleados_demo;
idnombreemailsalariodepartamento
1Anaana@empresa.com35000.00General
2Luisluis@empresa.com42000.00General
3Evaeva@empresa.com38000.00General

Controlar la posición de la columna

Por defecto, la columna se añade al final. Puedes controlar su posición con FIRST o AFTER:

-- Al principio de la tabla
ALTER TABLE empleados_demo
    ADD COLUMN codigo CHAR(5) FIRST;
 
-- Después de una columna específica
ALTER TABLE empleados_demo
    ADD COLUMN telefono VARCHAR(20) AFTER email;

Ahora la tabla tiene esta estructura:

DESCRIBE empleados_demo;
FieldTypeNullKeyDefaultExtra
codigochar(5)YESNULL
idintNOPRINULLauto_increment
nombrevarchar(50)NONULL
emailvarchar(100)YESNULL
telefonovarchar(20)YESNULL
salariodecimal(8,2)YESNULL
departamentovarchar(50)YESGeneral

Modificar una columna

Para cambiar el tipo de datos, las restricciones o el valor por defecto de una columna existente:

ALTER TABLE empleados_demo
    MODIFY COLUMN email VARCHAR(150) NOT NULL;

Esto cambia el tamaño máximo de email de 100 a 150 caracteres y la convierte en obligatoria. Los datos existentes se mantienen, siempre que sean compatibles con la nueva definición. Si alguna fila tiene NULL en email y la nueva definición es NOT NULL, la operación falla.

Cambiar el nombre de una columna

Para renombrar una columna y opcionalmente cambiar su tipo:

ALTER TABLE empleados_demo
    CHANGE COLUMN salario sueldo DECIMAL(10, 2) NOT NULL;

CHANGE requiere especificar tanto el nombre antiguo como el nuevo, además del tipo de datos completo. Si solo quieres cambiar el nombre sin modificar el tipo, debes repetir la definición del tipo.

MySQL 8.0 también permite renombrar sin redefinir el tipo:

ALTER TABLE empleados_demo
    RENAME COLUMN sueldo TO salario;

RENAME COLUMN solo cambia el nombre. Es más seguro porque no hay riesgo de modificar accidentalmente el tipo de datos.

Eliminar una columna

ALTER TABLE empleados_demo
    DROP COLUMN codigo;

La columna y todos sus datos se eliminan permanentemente. Si la columna tiene índices o es referenciada por una clave foránea, MySQL devuelve un error. Debes eliminar primero las dependencias.

Añadir una restricción

Puedes añadir restricciones a columnas existentes:

-- Añadir UNIQUE
ALTER TABLE empleados_demo
    ADD CONSTRAINT uk_email UNIQUE (email);
 
-- Añadir CHECK
ALTER TABLE empleados_demo
    ADD CONSTRAINT chk_salario CHECK (salario > 0);

Dar nombre a las restricciones (como uk_email y chk_salario) facilita referenciarlas si necesitas eliminarlas o modificarlas después.

Eliminar una restricción

-- Eliminar UNIQUE
ALTER TABLE empleados_demo
    DROP INDEX uk_email;
 
-- Eliminar CHECK
ALTER TABLE empleados_demo
    DROP CHECK chk_salario;

Las restricciones UNIQUE se eliminan con DROP INDEX porque MySQL las implementa internamente como índices. Las restricciones CHECK se eliminan con DROP CHECK.

Añadir y eliminar claves foráneas

-- Crear tabla referenciada
CREATE TABLE departamentos_demo (
    id INT AUTO_INCREMENT PRIMARY KEY,
    nombre VARCHAR(50) NOT NULL
);
 
-- Añadir clave foránea
ALTER TABLE empleados_demo
    ADD COLUMN departamento_id INT,
    ADD CONSTRAINT fk_departamento
        FOREIGN KEY (departamento_id) REFERENCES departamentos_demo(id)
        ON DELETE SET NULL;

Para eliminar la clave foránea:

ALTER TABLE empleados_demo
    DROP FOREIGN KEY fk_departamento;

Eliminar la clave foránea no elimina la columna ni el índice asociado. Si también quieres eliminar el índice:

ALTER TABLE empleados_demo
    DROP INDEX fk_departamento;

Renombrar la tabla

ALTER TABLE empleados_demo
    RENAME TO personal_demo;

Esto cambia el nombre de la tabla. Las claves foráneas que referencian esta tabla se actualizan automáticamente.

Múltiples cambios en una sentencia

La ventaja principal de ALTER TABLE es que puedes combinar múltiples operaciones:

ALTER TABLE personal_demo
    ADD COLUMN fecha_alta DATE,
    MODIFY COLUMN nombre VARCHAR(100) NOT NULL,
    DROP COLUMN telefono,
    RENAME TO empleados_demo;

MySQL ejecuta todas las operaciones en una sola pasada por la tabla, lo que es significativamente más rápido que ejecutar cuatro sentencias ALTER TABLE separadas, especialmente en tablas con muchos datos.

Cambiar opciones de tabla

ALTER TABLE empleados_demo
    ENGINE = InnoDB,
    DEFAULT CHARSET = utf8mb4,
    COMMENT = 'Tabla de prueba para empleados';

Cambiar el motor de almacenamiento reconstruye la tabla completa, lo que puede llevar tiempo en tablas grandes.

Consideraciones de rendimiento

En tablas con millones de filas, ALTER TABLE puede ser una operación costosa. Muchas operaciones requieren crear una copia de la tabla con la nueva estructura, copiar todos los datos, y reemplazar la tabla original. Durante este proceso, la tabla puede estar bloqueada para escrituras.

MySQL 8.0 soporta algunas operaciones "en línea" que no bloquean la tabla:

ALTER TABLE empleados_demo
    ADD COLUMN nota TEXT,
    ALGORITHM=INPLACE,
    LOCK=NONE;

ALGORITHM=INPLACE indica que MySQL no debe copiar la tabla. LOCK=NONE indica que no debe bloquear las lecturas ni escrituras. Si la operación no soporta estos modos, MySQL devuelve un error en lugar de degradar silenciosamente.

No todas las operaciones soportan INPLACE. Añadir una columna al final generalmente sí, pero cambiar el tipo de datos de una columna normalmente no.

Limpieza

DROP TABLE IF EXISTS empleados_demo;
DROP TABLE IF EXISTS departamentos_demo;

En los siguientes artículos exploraremos en detalle las operaciones individuales de ALTER TABLE: añadir columnas, modificar columnas y eliminar columnas.

Escrito por Eduardo Lázaro