ENUM

ENUM define una columna que solo puede contener un valor de una lista predefinida. Internamente, MySQL almacena cada valor como un entero (1, 2, 3...), lo que hace que sea compacto y rápido de comparar. Es útil para columnas con un conjunto pequeño y estable de opciones como estados, prioridades o categorías fijas.

Sintaxis

CREATE TABLE nombre_tabla (
    columna ENUM('valor1', 'valor2', 'valor3') NOT NULL
);

Cada valor se define como una cadena entre comillas. MySQL asigna un índice numérico secuencial empezando en 1.

Ejemplo básico

CREATE TABLE tickets (
    id INT AUTO_INCREMENT PRIMARY KEY,
    titulo VARCHAR(200) NOT NULL,
    prioridad ENUM('baja', 'media', 'alta', 'crítica') NOT NULL DEFAULT 'media',
    estado ENUM('abierto', 'en progreso', 'resuelto', 'cerrado') NOT NULL DEFAULT 'abierto'
);
 
INSERT INTO tickets (titulo, prioridad, estado) VALUES
('Error en login', 'alta', 'en progreso'),
('Actualizar docs', 'baja', 'abierto'),
('Caída del servidor', 'crítica', 'resuelto'),
('Mejorar UI', 'media', 'abierto');
 
SELECT * FROM tickets;
idtituloprioridadestado
1Error en loginaltaen progreso
2Actualizar docsbajaabierto
3Caída del servidorcríticaresuelto
4Mejorar UImediaabierto

MySQL rechaza valores que no están en la lista:

INSERT INTO tickets (titulo, prioridad) VALUES ('Test', 'urgente');
ERROR 1265 (01000): Data truncated for column 'prioridad' at row 1

ENUM en tienda_mysql

La tabla pedidos usa ENUM para el estado del pedido:

SELECT estado, COUNT(*) AS total
FROM pedidos
GROUP BY estado
ORDER BY FIELD(estado, 'pendiente', 'procesando', 'enviado', 'entregado', 'cancelado');
estadototal
pendiente7
procesando4
enviado4
entregado7
cancelado3
SELECT id, cliente_id, estado, total
FROM pedidos
WHERE estado = 'cancelado';
idcliente_idestadototal
1612cancelado699.00
171cancelado49.99
2519cancelado149.99

Índices numéricos internos

Cada valor ENUM tiene un índice numérico. El primer valor es 1, el segundo es 2, etc. La cadena vacía tiene índice 0:

SELECT
    prioridad,
    prioridad + 0 AS indice
FROM tickets
ORDER BY prioridad + 0;
prioridadindice
baja1
media2
alta3
crítica4

Puedes consultar por índice, aunque no es recomendable:

-- Ambas son equivalentes
SELECT * FROM tickets WHERE prioridad = 'alta';
SELECT * FROM tickets WHERE prioridad = 3;

Ordenamiento por ENUM

ENUM ordena por el índice numérico, no alfabéticamente. Esto es una ventaja cuando defines los valores en un orden lógico:

SELECT titulo, prioridad
FROM tickets
ORDER BY prioridad;
tituloprioridad
Actualizar docsbaja
Mejorar UImedia
Error en loginalta
Caída del servidorcrítica

El orden sigue la definición: baja (1), media (2), alta (3), crítica (4). Si ordenaras alfabéticamente, el orden sería: alta, baja, crítica, media, que no tiene sentido lógico.

Para forzar orden alfabético, usa CAST:

SELECT titulo, prioridad FROM tickets ORDER BY CAST(prioridad AS CHAR);

Almacenamiento

ENUM es muy eficiente en espacio:

Valores en ENUMBytes
1 a 2551 byte
256 a 65,5352 bytes

Una columna ENUM con 5 valores ocupa solo 1 byte por fila, mientras que un VARCHAR(20) con los mismos valores podría ocupar 5-21 bytes.

Filtrar con ENUM

Puedes usar todos los operadores habituales:

-- Valores específicos
SELECT titulo FROM tickets WHERE prioridad = 'alta';
 
-- Múltiples valores con IN
SELECT titulo FROM tickets WHERE estado IN ('abierto', 'en progreso');
 
-- Comparaciones con índice (prioridad >= alta)
SELECT titulo FROM tickets WHERE prioridad >= 'alta';
titulo
Error en login
Caída del servidor

La comparación >= funciona con el índice numérico: alta (3) y crítica (4) son mayores o iguales que 'alta' (3).

Modificar valores ENUM

Para añadir o cambiar valores, necesitas ALTER TABLE:

-- Añadir un valor al final
ALTER TABLE tickets MODIFY prioridad ENUM('baja', 'media', 'alta', 'crítica', 'bloqueante');
 
-- Añadir un valor en medio (requiere redefinir toda la lista)
ALTER TABLE tickets MODIFY prioridad ENUM('mínima', 'baja', 'media', 'alta', 'crítica', 'bloqueante');

Añadir un valor al final es rápido (solo cambia los metadatos). Insertar un valor en medio o reordenar requiere reconstruir la tabla, porque los índices numéricos cambian.

ENUM y NULL

Si la columna permite NULL, hay tres tipos de valores posibles: los valores definidos, la cadena vacía (si el modo no es estricto) y NULL:

CREATE TABLE test_enum (
    valor ENUM('a', 'b', 'c')
);
 
INSERT INTO test_enum VALUES ('a'), (NULL);
 
SELECT valor, valor IS NULL AS es_null FROM test_enum;
valores_null
a0
1

ENUM vs CHECK

Una alternativa a ENUM es usar VARCHAR con una restricción CHECK:

-- Con ENUM
estado ENUM('activo', 'inactivo', 'suspendido')
 
-- Con CHECK
estado VARCHAR(20) CHECK (estado IN ('activo', 'inactivo', 'suspendido'))
CaracterísticaENUMVARCHAR + CHECK
Almacenamiento1-2 bytesLongitud del texto
Modificar valoresALTER TABLE MODIFYALTER TABLE DROP/ADD CHECK
Portabilidad SQLSolo MySQLEstándar SQL
OrdenamientoPor posición definidaAlfabético
Ver valores válidosSHOW COLUMNSConsultar restricciones

Si la portabilidad entre bases de datos importa, usa VARCHAR con CHECK. Si el rendimiento y el espacio son prioritarios, usa ENUM.

Desventajas de ENUM

Cambiar valores requiere DDL: Añadir, eliminar o reordenar valores requiere ALTER TABLE, que puede bloquear la tabla en tablas grandes.

No es estándar SQL: ENUM es específico de MySQL. Si migras a PostgreSQL, tendrás que crear un tipo ENUM diferente o usar CHECK.

Los índices cambian: Si insertas un valor nuevo en medio de la lista, los índices numéricos de los valores posteriores cambian, lo que puede romper código que dependa de los índices.

Limpieza

DROP TABLE IF EXISTS tickets;
DROP TABLE IF EXISTS test_enum;

En el siguiente artículo veremos SET, similar a ENUM pero permitiendo múltiples valores simultáneos en una columna.

Escrito por Eduardo Lázaro