VARBINARY

BINARY y VARBINARY almacenan cadenas de bytes de longitud fija y variable, respectivamente. Son los equivalentes binarios de CHAR y VARCHAR: misma mecánica de almacenamiento pero sin conjunto de caracteres ni collation. Las comparaciones son siempre byte a byte (case-sensitive y sensibles a acentos). Son ideales para hashes, tokens, UUIDs en formato binario y datos pequeños que requieren comparaciones exactas.

Sintaxis

columna BINARY(longitud)     -- Longitud fija: 0 a 255 bytes
columna VARBINARY(longitud)  -- Longitud variable: 0 a 65,535 bytes

Diferencias entre BINARY y VARBINARY

CaracterísticaBINARY(n)VARBINARY(n)
LongitudFijaVariable
AlmacenamientoSiempre n bytesLargo real + 1-2 bytes
RellenoRellena con 0x00Sin relleno
Máximo255 bytes65,535 bytes

Ejemplo básico

CREATE TABLE tokens (
    id INT AUTO_INCREMENT PRIMARY KEY,
    usuario VARCHAR(50) NOT NULL,
    token VARBINARY(64) NOT NULL,
    hash_password BINARY(32) NOT NULL,
    creado_en TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
 
INSERT INTO tokens (usuario, token, hash_password) VALUES
('maria', UNHEX('a1b2c3d4e5f6'), UNHEX(SHA2('password123', 256))),
('carlos', UNHEX('f6e5d4c3b2a1'), UNHEX(SHA2('seguro456', 256)));
 
SELECT usuario, HEX(token) AS token_hex, LENGTH(token) AS bytes FROM tokens;
usuariotoken_hexbytes
mariaA1B2C3D4E5F66
carlosF6E5D4C3B2A16

BINARY vs CHAR

La diferencia principal es cómo se comparan y almacenan:

CREATE TABLE comparacion (
    val_char CHAR(5),
    val_binary BINARY(5)
);
 
INSERT INTO comparacion VALUES ('abc', 'abc');
 
SELECT
    val_char = 'ABC' AS char_insensible,
    val_binary = CAST('ABC' AS BINARY) AS binary_sensible,
    HEX(val_char) AS hex_char,
    HEX(val_binary) AS hex_binary
FROM comparacion;
char_insensiblebinary_sensiblehex_charhex_binary
106162636162630000

CHAR compara sin distinguir mayúsculas. BINARY compara byte a byte (0x61 ≠ 0x41). BINARY(5) rellena con 0x00 hasta 5 bytes, lo que se ve en la representación hexadecimal.

Almacenar UUIDs eficientemente

Un UUID como 550e8400-e29b-41d4-a716-446655440000 ocupa 36 caracteres como CHAR(36). En formato binario ocupa solo 16 bytes:

CREATE TABLE entidades (
    id BINARY(16) PRIMARY KEY,
    nombre VARCHAR(100) NOT NULL
);
 
-- Insertar UUID como binario
INSERT INTO entidades (id, nombre)
VALUES (UUID_TO_BIN(UUID()), 'Entidad A');
 
INSERT INTO entidades (id, nombre)
VALUES (UUID_TO_BIN(UUID()), 'Entidad B');
 
-- Leer UUID como texto
SELECT BIN_TO_UUID(id) AS uuid, nombre FROM entidades;
uuidnombre
550e8400-e29b-41d4-a716-446655440000Entidad A
6ba7b810-9dad-11d1-80b4-00c04fd430c8Entidad B

UUID_TO_BIN convierte un UUID de texto a 16 bytes binarios. BIN_TO_UUID hace la conversión inversa. Con la opción UUID_TO_BIN(UUID(), 1), MySQL reordena los bytes para un mejor rendimiento del índice.

AlmacenamientoTipoBytes
UUID como CHAR(36)Texto36
UUID como BINARY(16)Binario16
Ahorro por fila-20 bytes (56%)

Almacenar hashes

Los hashes criptográficos tienen longitud fija, lo que los hace candidatos perfectos para BINARY:

CREATE TABLE credenciales (
    usuario_id INT PRIMARY KEY,
    password_hash BINARY(32) NOT NULL,  -- SHA-256 = 32 bytes
    salt BINARY(16) NOT NULL
);
 
-- SHA-256 produce 32 bytes (64 caracteres hex)
INSERT INTO credenciales VALUES
(1, UNHEX(SHA2('mi_password', 256)), RANDOM_BYTES(16));
 
SELECT
    usuario_id,
    HEX(password_hash) AS hash,
    LENGTH(password_hash) AS bytes
FROM credenciales;
usuario_idhashbytes
1EF92B778...32
HashLongitudTipo recomendado
MD516 bytesBINARY(16)
SHA-120 bytesBINARY(20)
SHA-25632 bytesBINARY(32)
SHA-51264 bytesBINARY(64)

Almacenar direcciones IP

Las direcciones IPv4 se pueden almacenar como BINARY(4) (4 bytes) en lugar de VARCHAR(15) (hasta 15 bytes):

CREATE TABLE accesos (
    id INT AUTO_INCREMENT PRIMARY KEY,
    ip VARBINARY(16) NOT NULL,
    accion VARCHAR(50),
    fecha TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
 
-- IPv4
INSERT INTO accesos (ip, accion) VALUES (INET6_ATON('192.168.1.1'), 'login');
 
-- IPv6
INSERT INTO accesos (ip, accion) VALUES (INET6_ATON('::1'), 'login');
 
SELECT INET6_NTOA(ip) AS ip, accion FROM accesos;
ipaccion
192.168.1.1login
::1login

INET6_ATON convierte una IP (v4 o v6) a binario. INET6_NTOA hace la conversión inversa. VARBINARY(16) soporta tanto IPv4 (4 bytes) como IPv6 (16 bytes).

Comparaciones binarias

SELECT
    CAST('hello' AS BINARY) = CAST('Hello' AS BINARY) AS sensible,
    CAST('hello' AS BINARY) = CAST('hello' AS BINARY) AS exacto,
    CAST('café' AS BINARY) = CAST('cafe' AS BINARY) AS acentos;
sensibleexactoacentos
010

Las comparaciones binarias son estrictas: distinguen mayúsculas, acentos y cualquier diferencia de bytes.

Cuándo usar BINARY/VARBINARY

Caso de usoTipo recomendado
Hash MD5/SHABINARY(16/20/32/64)
UUID binarioBINARY(16)
Dirección IPVARBINARY(16)
Token de sesiónVARBINARY(64)
Datos encriptados pequeñosVARBINARY(n)
Archivos grandesBLOB/MEDIUMBLOB

Usa BINARY cuando la longitud es siempre la misma (hashes, UUIDs). Usa VARBINARY cuando varía (tokens, datos encriptados de longitud variable).

Limpieza

DROP TABLE IF EXISTS tokens;
DROP TABLE IF EXISTS comparacion;
DROP TABLE IF EXISTS entidades;
DROP TABLE IF EXISTS credenciales;
DROP TABLE IF EXISTS accesos;

Con esto completamos la sección de tipos de datos. Hemos cubierto los tipos numéricos (INT, DECIMAL, FLOAT/DOUBLE, BOOLEAN), los tipos de cadena (VARCHAR/CHAR, TEXT, ENUM, SET), los tipos temporales (DATE, TIME, DATETIME, TIMESTAMP) y los tipos binarios (BLOB, VARBINARY). En la siguiente sección exploraremos los conjuntos de caracteres y las collations en MySQL.

Escrito por Eduardo Lázaro