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 bytesDiferencias entre BINARY y VARBINARY
| Característica | BINARY(n) | VARBINARY(n) |
|---|---|---|
| Longitud | Fija | Variable |
| Almacenamiento | Siempre n bytes | Largo real + 1-2 bytes |
| Relleno | Rellena con 0x00 | Sin relleno |
| Máximo | 255 bytes | 65,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;| usuario | token_hex | bytes |
|---|---|---|
| maria | A1B2C3D4E5F6 | 6 |
| carlos | F6E5D4C3B2A1 | 6 |
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_insensible | binary_sensible | hex_char | hex_binary |
|---|---|---|---|
| 1 | 0 | 616263 | 6162630000 |
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;| uuid | nombre |
|---|---|
| 550e8400-e29b-41d4-a716-446655440000 | Entidad A |
| 6ba7b810-9dad-11d1-80b4-00c04fd430c8 | Entidad 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.
| Almacenamiento | Tipo | Bytes |
|---|---|---|
| UUID como CHAR(36) | Texto | 36 |
| UUID como BINARY(16) | Binario | 16 |
| 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_id | hash | bytes |
|---|---|---|
| 1 | EF92B778... | 32 |
| Hash | Longitud | Tipo recomendado |
|---|---|---|
| MD5 | 16 bytes | BINARY(16) |
| SHA-1 | 20 bytes | BINARY(20) |
| SHA-256 | 32 bytes | BINARY(32) |
| SHA-512 | 64 bytes | BINARY(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;| ip | accion |
|---|---|
| 192.168.1.1 | login |
| ::1 | login |
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;| sensible | exacto | acentos |
|---|---|---|
| 0 | 1 | 0 |
Las comparaciones binarias son estrictas: distinguen mayúsculas, acentos y cualquier diferencia de bytes.
Cuándo usar BINARY/VARBINARY
| Caso de uso | Tipo recomendado |
|---|---|
| Hash MD5/SHA | BINARY(16/20/32/64) |
| UUID binario | BINARY(16) |
| Dirección IP | VARBINARY(16) |
| Token de sesión | VARBINARY(64) |
| Datos encriptados pequeños | VARBINARY(n) |
| Archivos grandes | BLOB/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
