Manieren zonder dynamische SQL
Er is geen cast van hexadecimale getallen in text
weergave naar een numeriek type, maar we kunnen bit(n)
. gebruiken als tussenstop. Er zijn ongedocumenteerde casts van bitstrings (bit(n)
) naar typen gehele getallen (int2
, int4
, int8
) - de interne representatie is binair compatibel. Ik citeer Tom Lane:
Dit is gebaseerd op enig ongedocumenteerd gedrag van de bit-type inputconverter, maar ik zie geen reden om te verwachten dat dit zou breken. Een mogelijk groter probleem is dat het PG>=8.3 vereist, omdat er daarvoor geen tekst naar bit werd gegoten.
integer
voor maximaal 8 hexadecimale cijfers
Maximaal 8 hexadecimale cijfers kunnen worden geconverteerd naar bit(32)
en vervolgens gedwongen tot integer
(standaard 4-byte integer):
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 gebruikt een ondertekend geheel getal, dus hexadecimale getallen boven '7fffffff'
overlopen in negatief geheel getal nummers. Dit is nog steeds een geldige, unieke weergave, maar de betekenis is anders. Als dat van belang is, schakelt u over naar bigint
; zie hieronder.
Voor meer dan 8 hexadecimale cijfers worden de minst significante tekens (te veel naar rechts) afgekapt .
4 bits in een bit string codeer 1 hexadecimaal cijfer . Hex-nummers van bekende lengte kunnen worden gegoten naar de respectievelijke bit(n)
direct. U kunt ook hexadecimale getallen van onbekende lengte . gebruiken met voorloopnullen (0
) zoals gedemonstreerd en gecast naar bit(32)
. Voorbeeld met 7 hexadecimale cijfers en int
of 8 cijfers en bigint
:
SELECT ('x'|| 'deafbee')::bit(28)::int
, ('x'|| 'deadbeef')::bit(32)::bigint;
int4 | int8
-----------+------------
233503726 | 3735928559
bigint
voor maximaal 16 hexadecimale cijfers
Er kunnen maximaal 16 hexadecimale cijfers worden geconverteerd naar bit(64)
en vervolgens gedwongen tot bigint
(int8
, 8-byte integer) - weer overlopend in negatieve getallen in de bovenste helft:
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
voor maximaal 32 hexadecimale cijfers
De Postgres uuid
gegevenstype is geen numeriek type . Maar het is het meest efficiënte type in standaard Postgres om tot 32 hexadecimale cijfers op te slaan, terwijl het slechts 16 bytes aan opslagruimte in beslag neemt. Er is een directe cast van text
naar uuid
(geen behoefte aan bit(n)
als waypoint), maar precies 32 hexadecimale cijfers zijn vereist.
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
Zoals je kunt zien, is de standaarduitvoer een reeks hexadecimale cijfers met typische scheidingstekens voor UUID.
md5-hash
Dit is vooral handig om md5-hashes op te slaan :
SELECT md5('Store hash for long string, maybe for index?')::uuid AS md5_hash;
md5_hash
--------------------------------------
02e10e94-e895-616e-8e23-bb7f8025da42
Zie:
- Wat is het optimale gegevenstype voor een MD5-veld?