VARCHAR y CHAR
VARCHAR y CHAR almacenan cadenas de texto cortas. La diferencia principal es que CHAR tiene longitud fija y VARCHAR tiene longitud variable. CHAR siempre ocupa el mismo espacio sin importar la longitud del texto. VARCHAR ocupa solo el espacio necesario más 1 o 2 bytes para almacenar la longitud. En la mayoría de los casos, VARCHAR es la mejor opción.
Sintaxis
columna CHAR(longitud) -- Longitud fija: 0 a 255
columna VARCHAR(longitud) -- Longitud variable: 0 a 65,535La longitud indica el número máximo de caracteres (no bytes). Con el conjunto de caracteres utf8mb4, un carácter puede ocupar hasta 4 bytes.
Diferencias entre CHAR y VARCHAR
| Característica | CHAR(n) | VARCHAR(n) |
|---|---|---|
| Longitud | Fija | Variable |
| Almacenamiento | Siempre n bytes | Largo real + 1-2 bytes |
| Máximo | 255 caracteres | 65,535 caracteres |
| Relleno | Rellena con espacios | Sin relleno |
| Rendimiento | Ligeramente más rápido | Más eficiente en espacio |
VARCHAR
VARCHAR almacena cadenas de longitud variable. Solo ocupa el espacio necesario:
CREATE TABLE mensajes (
id INT AUTO_INCREMENT PRIMARY KEY,
asunto VARCHAR(200) NOT NULL,
remitente VARCHAR(100) NOT NULL,
contenido VARCHAR(1000)
);
INSERT INTO mensajes (asunto, remitente, contenido) VALUES
('Bienvenida', 'admin@email.com', 'Hola, bienvenido al sistema'),
('Oferta', 'ventas@email.com', 'Descuento del 20%'),
('Alerta', 'sistema@email.com', 'Error en servidor');
SELECT id, asunto, remitente, LENGTH(asunto) AS bytes FROM mensajes;| id | asunto | remitente | bytes |
|---|---|---|---|
| 1 | Bienvenida | admin@email.com | 10 |
| 2 | Oferta | ventas@email.com | 6 |
| 3 | Alerta | sistema@email.com | 6 |
LENGTH devuelve el número de bytes almacenados. Una cadena de 6 caracteres ocupa 6 bytes (más 1 byte para la longitud interna), no los 200 bytes del máximo declarado.
VARCHAR en tienda_mysql
Nuestra base de datos usa VARCHAR extensivamente:
SELECT
COLUMN_NAME AS columna,
COLUMN_TYPE AS tipo,
CHARACTER_MAXIMUM_LENGTH AS max_chars
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'tienda_mysql'
AND DATA_TYPE = 'varchar'
ORDER BY CHARACTER_MAXIMUM_LENGTH DESC
LIMIT 10;| columna | tipo | max_chars |
|---|---|---|
| direccion | varchar(255) | 255 |
| nombre | varchar(200) | 200 |
| varchar(150) | 150 | |
| apellidos | varchar(100) | 100 |
| nombre | varchar(100) | 100 |
| puesto | varchar(100) | 100 |
| ciudad | varchar(100) | 100 |
| etiqueta | varchar(50) | 50 |
| telefono | varchar(20) | 20 |
| codigo_postal | varchar(10) | 10 |
Cada columna tiene un límite apropiado para su contenido: 200 para nombres de producto, 150 para emails, 10 para códigos postales.
CHAR
CHAR almacena cadenas de longitud fija. Siempre ocupa exactamente n bytes, rellenando con espacios al final si el valor es más corto:
CREATE TABLE codigos (
id INT AUTO_INCREMENT PRIMARY KEY,
pais CHAR(2) NOT NULL,
moneda CHAR(3) NOT NULL,
codigo_iso CHAR(5)
);
INSERT INTO codigos (pais, moneda, codigo_iso) VALUES
('ES', 'EUR', 'ES-MD'),
('US', 'USD', 'US-NY'),
('JP', 'JPY', 'JP-TK'),
('GB', 'GBP', 'GB-LN');
SELECT pais, moneda, codigo_iso FROM codigos;| pais | moneda | codigo_iso |
|---|---|---|
| ES | EUR | ES-MD |
| US | USD | US-NY |
| JP | JPY | JP-TK |
| GB | GBP | GB-LN |
CHAR(2) es perfecto para códigos de país ISO. CHAR(3) para códigos de moneda. Todos los valores tienen exactamente la misma longitud, así que CHAR no desperdicia espacio.
Relleno de espacios en CHAR
CHAR rellena con espacios a la derecha, pero MySQL los elimina automáticamente al recuperar el valor:
CREATE TABLE test_padding (
val_char CHAR(10),
val_varchar VARCHAR(10)
);
INSERT INTO test_padding VALUES ('hola', 'hola');
SELECT
val_char,
val_varchar,
LENGTH(val_char) AS len_char,
LENGTH(val_varchar) AS len_varchar,
CONCAT('[', val_char, ']') AS char_visual,
CONCAT('[', val_varchar, ']') AS varchar_visual
FROM test_padding;| val_char | val_varchar | len_char | len_varchar | char_visual | varchar_visual |
|---|---|---|---|---|---|
| hola | hola | 4 | 4 | [hola] | [hola] |
Aunque CHAR(10) almacena 10 bytes internamente, MySQL elimina los espacios finales al leer. La longitud reportada es 4, no 10. Esto significa que los espacios finales significativos se pierden con CHAR.
Almacenamiento
VARCHAR almacena el contenido real más 1 o 2 bytes de prefijo de longitud:
| Contenido | CHAR(20) | VARCHAR(20) |
|---|---|---|
| '' (vacío) | 20 bytes | 1 byte |
| 'abc' | 20 bytes | 4 bytes |
| '12345678901234567890' | 20 bytes | 21 bytes |
El prefijo de longitud de VARCHAR usa 1 byte si el máximo es 255 o menos, y 2 bytes si supera 255.
Longitud máxima
-- CHAR: máximo 255 caracteres
columna CHAR(255) -- OK
-- columna CHAR(256) -- Error
-- VARCHAR: máximo teórico 65,535 caracteres
-- pero limitado por el tamaño máximo de fila (65,535 bytes)
columna VARCHAR(1000) -- OK
columna VARCHAR(16383) -- OK con utf8mb4 (16383 × 4 = 65,532 bytes)El límite real de VARCHAR depende del conjunto de caracteres. Con utf8mb4 (4 bytes por carácter), el máximo práctico es alrededor de 16,383 caracteres. Si necesitas más, usa TEXT.
CHAR_LENGTH vs LENGTH
LENGTH devuelve bytes, CHAR_LENGTH devuelve caracteres. Con caracteres multibyte, los resultados difieren:
SELECT
'café' AS texto,
LENGTH('café') AS bytes,
CHAR_LENGTH('café') AS caracteres;| texto | bytes | caracteres |
|---|---|---|
| café | 5 | 4 |
La é ocupa 2 bytes en UTF-8, así que 'café' tiene 4 caracteres pero 5 bytes. Usa CHAR_LENGTH cuando necesites contar caracteres.
Comparaciones
Las comparaciones de CHAR y VARCHAR son insensibles a mayúsculas por defecto (depende del collation):
SELECT
'Hola' = 'hola' AS comparacion,
'Hola' = 'HOLA' AS mayusculas,
'abc' = 'abc ' AS con_espacios;| comparacion | mayusculas | con_espacios |
|---|---|---|
| 1 | 1 | 1 |
MySQL ignora espacios finales en comparaciones y ordena sin distinguir mayúsculas con el collation por defecto (utf8mb4_0900_ai_ci). Si necesitas comparaciones exactas, usa BINARY:
SELECT
BINARY 'Hola' = 'hola' AS binario,
'Hola' COLLATE utf8mb4_bin = 'hola' AS con_collation;| binario | con_collation |
|---|---|
| 0 | 0 |
Cuándo usar CHAR
CHAR es la mejor opción cuando todos los valores tienen exactamente la misma longitud:
-- Códigos fijos
pais CHAR(2) -- ES, US, JP
moneda CHAR(3) -- EUR, USD, JPY
estado CHAR(1) -- A, I, P
hash_md5 CHAR(32) -- Siempre 32 caracteres
uuid_hex CHAR(36) -- Siempre 36 caracteres con guionesCuándo usar VARCHAR
VARCHAR es mejor cuando la longitud varía entre valores:
-- Longitud variable
nombre VARCHAR(100) -- 'Ana' vs 'María del Carmen'
email VARCHAR(150) -- 'a@b.com' vs 'nombre.largo@dominio.empresa.com'
direccion VARCHAR(255) -- Longitudes muy variables
telefono VARCHAR(20) -- Con/sin prefijo internacionalTruncamiento
Si insertas un valor más largo que el máximo, MySQL trunca o da error según el modo SQL:
CREATE TABLE test_trunc (texto VARCHAR(5));
-- En modo estricto (por defecto en MySQL 8.0):
INSERT INTO test_trunc VALUES ('abcdefghij');ERROR 1406 (22001): Data too long for column 'texto' at row 1
En modo no estricto, MySQL trunca silenciosamente a 5 caracteres y genera un warning.
Elegir la longitud adecuada
Define la longitud basándote en los datos reales, no en un número arbitrario:
| Dato | Longitud recomendada |
|---|---|
| Nombre de persona | VARCHAR(100) |
| VARCHAR(150) o VARCHAR(255) | |
| Teléfono | VARCHAR(20) |
| Dirección | VARCHAR(255) |
| Código postal | VARCHAR(10) o CHAR(5) |
| URL | VARCHAR(2048) |
| Slug | VARCHAR(255) |
No uses VARCHAR(255) para todo por inercia. Una columna telefono VARCHAR(255) funciona, pero VARCHAR(20) documenta mejor los datos esperados y permite a MySQL optimizar mejor las tablas temporales.
Limpieza
DROP TABLE IF EXISTS mensajes;
DROP TABLE IF EXISTS codigos;
DROP TABLE IF EXISTS test_padding;
DROP TABLE IF EXISTS test_trunc;En el siguiente artículo veremos TEXT, el tipo para cadenas de texto largas que superan los límites de VARCHAR.
Escrito por Eduardo Lázaro
