PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Converti esadecimale nella rappresentazione testuale in numero decimale

Modi senza SQL dinamico

Non c'è cast da numeri esadecimali in text rappresentazione in un tipo numerico, ma possiamo usare bit(n) come punto di passaggio. Ci sono non documentati cast da stringhe di bit (bit(n) ) in tipi interi (int2 , int4 , int8 ) - la rappresentazione interna è binaria compatibile. Citando Tom Lane:

Questo si basa su un comportamento non documentato del convertitore di input di tipo bit, ma non vedo alcun motivo per aspettarmi che si rompa. Un problema forse più grande è che richiede PG>=8.3 poiché prima non c'era un cast da testo a bit.

integer per max. 8 cifre esadecimali

È possibile convertire fino a 8 cifre esadecimali in bit(32) e quindi forzato a integer (intero standard a 4 byte):

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 utilizza un tipo intero con segno, quindi i numeri esadecimali sopra '7fffffff' overflow in numero intero negativo numeri. Questa è ancora una rappresentazione valida e unica ma il significato è diverso. Se questo è importante, passa a bigint; vedi sotto.

Per più di 8 cifre esadecimali i caratteri meno significativi (in eccesso a destra) vengono troncati .

4 bit in una stringa di bit codificare 1 cifra esadecimale . I numeri esadecimali di lunghezza nota possono essere trasmessi al rispettivo bit(n) direttamente. In alternativa, riempi i numeri esadecimali di lunghezza sconosciuta con zeri iniziali (0 ) come dimostrato e cast su bit(32) . Esempio con 7 cifre esadecimali e int o 8 cifre e bigint :

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

bigint per max. 16 cifre esadecimali

È possibile convertire fino a 16 cifre esadecimali in bit(64) e poi costretto a bigint (int8 , intero a 8 byte) - traboccante di nuovo in numeri negativi nella metà superiore:

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 per max. 32 cifre esadecimali

Il uuid di Postgres il tipo di dati non è un tipo numerico . Ma è il tipo più efficiente in Postgres standard per memorizzare fino a 32 cifre esadecimali, occupando solo 16 byte di memoria. C'è un cast diretto da text a uuid (non c'è bisogno di bit(n) come waypoint), ma esattamente Sono necessarie 32 cifre esadecimali.

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

Come puoi vedere, l'output standard è una stringa di cifre esadecimali con i tipici separatori per UUID.

hash md5

Ciò è particolarmente utile per memorizzare hash md5 :

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

Vedi:

  • Qual ​​è il tipo di dati ottimale per un campo MD5?