sql >> Base de Datos >  >> RDS >> PostgreSQL

Convertir hexadecimal en representación de texto a número decimal

Formas sin SQL dinámico

No hay conversión de números hexadecimales en text representación a un tipo numérico, pero podemos usar bit(n) como punto de ruta. Hay indocumentados conversiones desde cadenas de bits (bit(n) ) a tipos enteros (int2 , int4 , int8 ) - la representación interna es compatible binaria. Citando a Tom Lane:

Esto se basa en un comportamiento no documentado del convertidor de entrada de tipo bit, pero no veo ninguna razón para esperar que se rompa. Un problema posiblemente más grande es que requiere PG>=8.3 ya que no había un textto bit cast antes de eso.

integer para máx. 8 dígitos hexadecimales

Se pueden convertir hasta 8 dígitos hexadecimales a bit(32) y luego obligado a integer (entero estándar de 4 bytes):

SELECT ('x' || lpad(hex, 8, '0'))::bit(32)::int AS int_val
FROM  (
   VALUES
      ('1'::text)
    , ('f')
    , ('100')
    , ('7fffffff')
    , ('80000000')     -- overflow into negative number
    , ('deadbeef')
    , ('ffffffff')
    , ('ffffffff123')  -- too long
   ) AS t(hex);
   int_val
------------
          1
         15
        256
 2147483647
-2147483648
 -559038737
         -1

Postgres usa un tipo entero con signo, por lo que los números hexadecimales por encima de '7fffffff' desbordamiento en entero negativo números. Esta sigue siendo una representación válida y única, pero el significado es diferente. Si eso importa, cambia a bigint; ver más abajo.

Para más de 8 dígitos hexadecimales, los caracteres menos significativos (exceso a la derecha) se truncan .

4 bits en una cadena de bits codifica 1 dígito hexadecimal . Los números hexadecimales de longitud conocida se pueden convertir al respectivo bit(n) directamente. Alternativamente, complete los números hexadecimales de longitud desconocida con ceros a la izquierda (0 ) como se muestra y convertir a bit(32) . Ejemplo con 7 dígitos hexadecimales y int o 8 dígitos y bigint :

SELECT ('x'|| 'deafbee')::bit(28)::int
     , ('x'|| 'deadbeef')::bit(32)::bigint;
  int4     | int8
-----------+------------
 233503726 | 3735928559

bigint para máx. 16 dígitos hexadecimales

Se pueden convertir hasta 16 dígitos hexadecimales a bit(64) y luego obligado a bigint (int8 , entero de 8 bytes) - desbordándose nuevamente en números negativos en la mitad superior:

SELECT ('x' || lpad(hex, 16, '0'))::bit(64)::bigint AS int8_val
FROM  (
   VALUES
      ('ff'::text)
    , ('7fffffff')
    , ('80000000')
    , ('deadbeef')
    , ('7fffffffffffffff')
    , ('8000000000000000')     -- overflow into negative number
    , ('ffffffffffffffff')
    , ('ffffffffffffffff123')  -- too long
   ) t(hex);
       int8_val
---------------------
                 255
          2147483647
          2147483648
          3735928559
 9223372036854775807
-9223372036854775808
                  -1
                  -1

uuid para máx. 32 dígitos hexadecimales

El uuid de Postgres el tipo de datos no es un tipo numérico . Pero es el tipo más eficiente en Postgres estándar para almacenar hasta 32 dígitos hexadecimales, ocupando solo 16 bytes de almacenamiento. Hay un reparto directo de text a uuid (sin necesidad de bit(n) como waypoint), pero exactamente Se requieren 32 dígitos hexadecimales.

SELECT lpad(hex, 32, '0')::uuid AS uuid_val
FROM  (
   VALUES ('ff'::text)
        , ('deadbeef')
        , ('ffffffffffffffff')
        , ('ffffffffffffffffffffffffffffffff')
        , ('ffffffffffffffffffffffffffffffff123') -- too long
   ) t(hex);
              uuid_val
--------------------------------------
 00000000-0000-0000-0000-0000000000ff
 00000000-0000-0000-0000-0000deadbeef
 00000000-0000-0000-ffff-ffffffffffff
 ffffffff-ffff-ffff-ffff-ffffffffffff
 ffffffff-ffff-ffff-ffff-ffffffffffff

Como puede ver, la salida estándar es una cadena de dígitos hexadecimales con separadores típicos para UUID.

hash md5

Esto es particularmente útil para almacenar hashes md5 :

SELECT md5('Store hash for long string, maybe for index?')::uuid AS md5_hash;
           md5_hash
--------------------------------------
 02e10e94-e895-616e-8e23-bb7f8025da42

Ver:

  • ¿Cuál es el tipo de datos óptimo para un campo MD5?