Sätt utan dynamisk SQL
Det finns ingen cast från hexadecimala nummer i text
representation till en numerisk typ, men vi kan använda bit(n)
som vägpunkt. Det finns odokumenterade casts från bitsträngar (bit(n)
) till heltalstyper (int2
, int4
, int8
) - den interna representationen är binärkompatibel. Citerar Tom Lane:
Detta förlitar sig på något odokumenterat beteende hos bit-typ inputconverter, men jag ser ingen anledning att förvänta sig att det skulle gå sönder. Ett möjligen större problem är att det kräver PG>=8.3 eftersom det inte fanns en text till bit cast innan dess.
integer
för max. 8 hexadecimala siffror
Upp till 8 hexadecimala siffror kan konverteras till bit(32)
och sedan tvingas till integer
(standard 4-byte heltal):
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 använder en signerad heltalstyp, så hexadecimala nummer ovanför '7fffffff'
svämmar över till negativt heltal tal. Detta är fortfarande en giltig, unik representation men innebörden är annorlunda. Om det spelar någon roll byter du till bigint
; se nedan.
För mer än 8 hexadecimala siffror blir de minst signifikanta tecknen (överskott till höger) trunkerade .
4 bitar koda i en bitsträng 1 hexadecimal siffra . Hexnummer med känd längd kan gjutas till respektive bit(n)
direkt. Alternativt kan du fylla på hexadecimala nummer med okänd längd med inledande nollor (0
) som visas och casta till bit(32)
. Exempel med 7 hexadecimala siffror och int
eller 8 siffror och bigint
:
SELECT ('x'|| 'deafbee')::bit(28)::int
, ('x'|| 'deadbeef')::bit(32)::bigint;
int4 | int8
-----------+------------
233503726 | 3735928559
bigint
för max. 16 hexadecimala siffror
Upp till 16 hexadecimala siffror kan konverteras till bit(64)
och sedan tvingas till bigint
(int8
, 8-byte heltal) - svämmar över till negativa tal i den övre halvan igen:
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
för max. 32 hexadecimala siffror
Postgres uuid
datatypen är inte en numerisk typ . Men det är den mest effektiva typen i standard Postgres att lagra upp till 32 hexadecimala siffror, som bara upptar 16 byte lagringsutrymme. Det finns en direkt rollbesättning från text
till uuid
(inget behov av bit(n)
som waypoint), men exakt 32 hexadecimala siffror krävs.
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
Som du kan se är standardutdata en sträng av hexadecimala siffror med typiska avgränsare för UUID.
md5 hash
Detta är särskilt användbart för att lagra md5-hashar :
SELECT md5('Store hash for long string, maybe for index?')::uuid AS md5_hash;
md5_hash
--------------------------------------
02e10e94-e895-616e-8e23-bb7f8025da42
Se:
- Vilken är den optimala datatypen för ett MD5-fält?