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,535

La 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ísticaCHAR(n)VARCHAR(n)
LongitudFijaVariable
AlmacenamientoSiempre n bytesLargo real + 1-2 bytes
Máximo255 caracteres65,535 caracteres
RellenoRellena con espaciosSin relleno
RendimientoLigeramente más rápidoMá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;
idasuntoremitentebytes
1Bienvenidaadmin@email.com10
2Ofertaventas@email.com6
3Alertasistema@email.com6

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;
columnatipomax_chars
direccionvarchar(255)255
nombrevarchar(200)200
emailvarchar(150)150
apellidosvarchar(100)100
nombrevarchar(100)100
puestovarchar(100)100
ciudadvarchar(100)100
etiquetavarchar(50)50
telefonovarchar(20)20
codigo_postalvarchar(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;
paismonedacodigo_iso
ESEURES-MD
USUSDUS-NY
JPJPYJP-TK
GBGBPGB-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_charval_varcharlen_charlen_varcharchar_visualvarchar_visual
holahola44[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:

ContenidoCHAR(20)VARCHAR(20)
'' (vacío)20 bytes1 byte
'abc'20 bytes4 bytes
'12345678901234567890'20 bytes21 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;
textobytescaracteres
café54

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;
comparacionmayusculascon_espacios
111

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;
binariocon_collation
00

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 guiones

Cuá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 internacional

Truncamiento

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:

DatoLongitud recomendada
Nombre de personaVARCHAR(100)
EmailVARCHAR(150) o VARCHAR(255)
TeléfonoVARCHAR(20)
DirecciónVARCHAR(255)
Código postalVARCHAR(10) o CHAR(5)
URLVARCHAR(2048)
SlugVARCHAR(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