TEXT

Los tipos TEXT almacenan cadenas de texto largas. Mientras que VARCHAR tiene un límite práctico de ~16,000 caracteres (con utf8mb4), TEXT puede almacenar hasta 4 GB de texto. MySQL ofrece cuatro variantes de TEXT con diferentes capacidades máximas. Son ideales para descripciones, comentarios, artículos y cualquier texto de longitud impredecible.

Los cuatro tipos TEXT

TipoTamaño máximoBytes
TINYTEXT255 bytesL + 1
TEXT65,535 bytes (~64 KB)L + 2
MEDIUMTEXT16,777,215 bytes (~16 MB)L + 3
LONGTEXT4,294,967,295 bytes (~4 GB)L + 4

L es la longitud real del texto almacenado. El prefijo (1-4 bytes) almacena la longitud.

Ejemplo básico

CREATE TABLE articulos (
    id INT AUTO_INCREMENT PRIMARY KEY,
    titulo VARCHAR(200) NOT NULL,
    resumen TEXT,
    contenido MEDIUMTEXT NOT NULL,
    metadata LONGTEXT
);
 
INSERT INTO articulos (titulo, resumen, contenido) VALUES
('Introducción a SQL', 'Una guía rápida sobre SQL básico', 'SQL es un lenguaje estándar para gestionar bases de datos relacionales...'),
('Guía de MySQL 8.0', 'Novedades de MySQL 8.0', 'MySQL 8.0 introdujo mejoras significativas en rendimiento y funcionalidad...');
 
SELECT id, titulo, LENGTH(contenido) AS bytes_contenido FROM articulos;
idtitulobytes_contenido
1Introducción a SQL74
2Guía de MySQL 8.077

TEXT en tienda_mysql

Nuestra base de datos usa TEXT en varias tablas:

SELECT TABLE_NAME AS tabla, COLUMN_NAME AS columna, DATA_TYPE AS tipo
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'tienda_mysql'
  AND DATA_TYPE = 'text'
ORDER BY TABLE_NAME;
tablacolumnatipo
categoriasdescripciontext
pedidosnotastext
productosdescripciontext
resenascomentariotext

Veamos ejemplos reales:

SELECT nombre, LEFT(descripcion, 50) AS descripcion_corta
FROM productos
WHERE descripcion IS NOT NULL
LIMIT 5;
nombredescripcion_corta
iPhone 15 ProSmartphone Apple con chip A17 Pro y cámara de 48M
Samsung Galaxy S24Smartphone Samsung con Galaxy AI y pantalla AMOLE
Google Pixel 8Smartphone Google con procesador Tensor G3
Xiaomi 14Smartphone Xiaomi con cámara Leica
MacBook Air M3Portátil Apple ultraligero con chip M3

LEFT(texto, n) extrae los primeros n caracteres. Es útil para mostrar previsualizaciones de campos TEXT largos.

TEXT vs VARCHAR

CaracterísticaVARCHAR(n)TEXT
Longitud máxima65,535 bytes (compartido con la fila)65,535 bytes (independiente)
DEFAULTSoporta valores por defectoNo soporta DEFAULT
ÍndiceCompletoSolo con prefijo
AlmacenamientoEn la fila (inline)Puntero en la fila, datos fuera
OrdenamientoSobre el valor completoSobre los primeros max_sort_length bytes

La diferencia clave de almacenamiento: VARCHAR se almacena directamente en la fila de la tabla. TEXT almacena un puntero en la fila y los datos reales en un área separada (overflow pages en InnoDB). Esto hace que las consultas que no usan la columna TEXT sean más rápidas, porque MySQL no necesita leer los datos de texto.

No soporta DEFAULT

-- Esto da error:
CREATE TABLE test_default (
    contenido TEXT DEFAULT 'valor'
);
ERROR 1101 (42000): BLOB, TEXT, GEOMETRY or JSON column 'contenido' can't have a default value

Para simular un default, usa un trigger o establece el valor en la lógica de la aplicación.

Indexar columnas TEXT

No puedes crear un índice completo sobre una columna TEXT. Necesitas un índice de prefijo:

CREATE TABLE posts (
    id INT AUTO_INCREMENT PRIMARY KEY,
    contenido TEXT NOT NULL,
    INDEX idx_contenido (contenido(100))  -- Indexa los primeros 100 caracteres
);

El número entre paréntesis indica cuántos caracteres se indexan. Un prefijo más largo da búsquedas más precisas pero ocupa más espacio en el índice.

Para búsquedas de texto completo, usa un índice FULLTEXT en lugar de un índice de prefijo:

ALTER TABLE posts ADD FULLTEXT INDEX ft_contenido (contenido);
 
SELECT * FROM posts WHERE MATCH(contenido) AGAINST('mysql' IN NATURAL LANGUAGE MODE);

Funciones útiles con TEXT

-- Longitud
SELECT
    comentario,
    CHAR_LENGTH(comentario) AS caracteres,
    LENGTH(comentario) AS bytes
FROM resenas
LIMIT 3;
comentariocaracteresbytes
Excelente teléfono, la cámara es espectacular4748
Muy buen móvil, pero la batería podría durar más5154
Gran rendimiento, aunque es caro3232
-- Buscar dentro del texto
SELECT nombre, comentario
FROM resenas r
JOIN productos p ON r.producto_id = p.id
WHERE comentario LIKE '%cámara%';
nombrecomentario
iPhone 15 ProExcelente teléfono, la cámara es espectacular

TINYTEXT, MEDIUMTEXT y LONGTEXT

TINYTEXT (255 bytes): Rara vez se usa. VARCHAR(255) es mejor porque soporta índices completos y valores por defecto.

MEDIUMTEXT (16 MB): Ideal para artículos largos, documentos, contenido HTML extenso.

LONGTEXT (4 GB): Para contenido muy grande como libros completos o logs extensos. Rara vez necesario.

CREATE TABLE documentos (
    id INT AUTO_INCREMENT PRIMARY KEY,
    titulo VARCHAR(200) NOT NULL,
    resumen TINYTEXT,           -- Hasta 255 bytes
    contenido TEXT,              -- Hasta 64 KB
    manual MEDIUMTEXT,           -- Hasta 16 MB
    archivo_completo LONGTEXT    -- Hasta 4 GB
);

En la práctica, TEXT (64 KB) cubre la mayoría de los casos. MEDIUMTEXT se usa para CMS o aplicaciones con contenido editorial extenso.

Truncamiento en ordenamiento

MySQL solo usa los primeros max_sort_length bytes (por defecto 1024) al ordenar columnas TEXT:

SHOW VARIABLES LIKE 'max_sort_length';
Variable_nameValue
max_sort_length1024

Si tienes textos que difieren después de los primeros 1024 bytes y necesitas ordenarlos correctamente, puedes aumentar este valor para tu sesión:

SET SESSION max_sort_length = 4096;

Buenas prácticas

Usa VARCHAR cuando la longitud máxima es predecible y menor a ~1000 caracteres. Usa TEXT cuando la longitud es impredecible o potencialmente larga.

Evita seleccionar columnas TEXT cuando no las necesitas:

-- Malo: trae todos los datos TEXT aunque no los uses
SELECT * FROM productos;
 
-- Mejor: selecciona solo las columnas necesarias
SELECT id, nombre, precio FROM productos;

Esto es importante porque los datos TEXT se almacenan fuera de la fila principal y leerlos requiere acceso adicional a disco.

Limpieza

DROP TABLE IF EXISTS articulos;
DROP TABLE IF EXISTS posts;
DROP TABLE IF EXISTS documentos;

En el siguiente artículo veremos ENUM, el tipo para columnas que solo pueden contener un valor de una lista predefinida.

Escrito por Eduardo Lázaro