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?