sqlpostgresqlto_hexbitwise

to_hex en PostgreSQL: convertir un entero en una cadena hexadecimal

Como to_hex(int) convierte un numero en cadena hex para colores, mascaras de bits y depuracion de flags, como invertirlo y como difieren MySQL y ClickHouse.

2 min de lecturaReferencesql · postgresql · to_hex · bitwise · mysql · clickhouse

La notacion hexadecimal es un formato comodo y legible para todo lo que en el fondo es un numero: colores, mascaras de bits, flags de permisos, hashes. En PostgreSQL la funcion to_hex(int) toma un entero y devuelve su representacion hex como cadena, sin prefijo 0x. Veamos escenarios practicos y como invertir la conversion.

to_hex basico

La funcion acepta un integer o bigint y devuelve text:

SELECT to_hex(255);        -- 'ff'
SELECT to_hex(4096);       -- '1000'
SELECT to_hex(16777215);   -- 'ffffff'

Detalles utiles:

  • El resultado siempre va en minusculas y sin ceros a la izquierda.
  • No hay prefijo 0x; si lo necesitas para mostrarlo, anadelo tu mismo: '0x' || to_hex(255).
  • Para numeros negativos PostgreSQL devuelve el hex en complemento a dos, no un signo menos: to_hex(-1) da 'ffffffff' para una entrada de 32 bits.

Cuando necesitas un ancho fijo (por ejemplo, dos caracteres por byte), rellena a la izquierda con lpad:

-- Always two hex digits, e.g. for a single byte channel
SELECT lpad(to_hex(15), 2, '0');   -- '0f'

Colores y mascaras de bits

Un caso clasico es montar un color hex a partir de tres canales RGB. Supongamos que la tabla de usuarios guarda el color del avatar como un entero:

SELECT id,
       '#' || lpad(to_hex(theme_color), 6, '0') AS css_color
FROM users
WHERE country = 'DE';

Asi el numero 16711680 se convierte en #ff0000, rojo puro. Rellenar a seis caracteres garantiza un CSS valido incluso cuando los bytes altos son cero.

Un segundo escenario frecuente son los flags de permisos empaquetados en un solo numero con un OR bit a bit. El hex hace legibles esas mascaras:

-- 1=read, 2=write, 4=admin packed into orders.status as a bitmask
SELECT id,
       status,
       to_hex(status)        AS status_hex,
       (status & 4) <> 0     AS is_admin
FROM orders
WHERE (status & 4) <> 0;

Depurar valores de flags

Cuando no esta claro que bits estan activos, muestra el numero en tres formas a la vez: decimal, hex y binario:

SELECT salary,
       to_hex(salary::int)              AS hex,
       (salary::int)::bit(32)           AS bits
FROM employees
WHERE dept = 'engineering';

Gotcha: to_hex solo funciona con tipos enteros. Si le pasas un numeric o un text obtienes un error; convierte la entrada de forma explicita: to_hex(salary::int). Y ojo con el signo: para bigint el complemento a dos es mas ancho, asi que to_hex(-1::bigint) devuelve 'ffffffffffffffff', no 'ffffffff'.

Invertir el hex de vuelta a numero

PostgreSQL no tiene un from_hex(int) directo, pero hay un truco limpio via el tipo bit: un prefijo x delante de un literal hex define una cadena de bits que puedes convertir a entero.

-- Parse hex text back into an integer
SELECT ('x' || lpad('ff', 8, '0'))::bit(32)::int;    -- 255
SELECT ('x' || lpad('1000', 8, '0'))::bit(32)::int;  -- 4096

El lpad a ocho caracteres importa: bit(32) necesita exactamente 32 bits, es decir 8 digitos hex. Para un bigint usa bit(64) y lpad(..., 16, '0'). El ciclo completo de ida y vuelta:

-- Round trip: int -> hex -> int
SELECT ('x' || lpad(to_hex(48879), 8, '0'))::bit(32)::int;  -- 48879

bytea y equivalentes en MySQL

Para datos binarios (bytea) en lugar de un solo numero, usa encode y decode con el formato hex:

-- Bytes to hex text and back
SELECT encode('PG'::bytea, 'hex');      -- '5047'
SELECT decode('5047', 'hex');           -- bytea \x5047

encode(..., 'hex') es ideal para hashes y bytes crudos; to_hex es para numeros.

MySQL pinta otro panorama:

  • HEX(255) devuelve 'FF' (en mayusculas!) y funciona tanto con numeros como con cadenas.
  • Para invertir, CONV('ff', 16, 10) pasa de hex a decimal, o UNHEX('5047') para bytes.
  • CONV(255, 10, 16) es un cambio flexible entre dos bases cualesquiera.
-- MySQL flavor
SELECT HEX(255),          -- 'FF'
       CONV('ff', 16, 10),-- '255'
       LPAD(HEX(15), 2, '0');  -- '0F'

ClickHouse ofrece hex(255) (tambien en mayusculas) y unhex('FF') para el inverso. Cuida la capitalizacion al comparar cadenas entre motores. En resumen: to_hex para numeros, encode/decode para bytes, y el inverso via bit en PostgreSQL o CONV/UNHEX en MySQL.

Practica con ejercicios reales

Resuelve ejercicios en el entrenador de SQL con corrección instantánea y pistas.

Abrir el entrenador