Wege ohne dynamisches SQL
Es gibt keine Umwandlung von Hex-Zahlen in text
Darstellung in einen numerischen Typ, aber wir können bit(n)
verwenden als Wegpunkt. Es gibt undokumentierte Umwandlungen von Bitfolgen (bit(n)
) in Integer-Typen (int2
, int4
, int8
) - die interne Darstellung ist binärkompatibel. Zitat von Tom Lane:
Dies beruht auf einem undokumentierten Verhalten des Bit-Typ-Eingabekonverters, aber ich sehe keinen Grund zu der Annahme, dass dies brechen würde. Ein möglicherweise größeres Problem ist, dass es PG>=8.3 erfordert, da es davor keine Text-to-Bit-Umwandlung gab.
integer
für max. 8 Hexadezimalziffern
Bis zu 8 Hexadezimalziffern können in bit(32)
umgewandelt werden und dann zu integer
gezwungen (standardmäßige 4-Byte-Ganzzahl):
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 verwendet einen vorzeichenbehafteten Integer-Typ, also Hexadezimalzahlen über '7fffffff'
Überlauf in negative Ganzzahl Zahlen. Dies ist immer noch eine gültige, eindeutige Darstellung, aber die Bedeutung ist anders. Wenn das wichtig ist, wechseln Sie zu bigint
; siehe unten.
Bei mehr als 8 Hexadezimalziffern werden die niederwertigsten Zeichen (Überschuss rechts) abgeschnitten .
4 Bit codieren Sie in einer Bitfolge 1 Hexadezimalziffer . Hex-Zahlen bekannter Länge können auf das jeweilige bit(n)
gecastet werden direkt. Füllen Sie alternativ Hexadezimalzahlen unbekannter Länge auf mit führenden Nullen (0
) wie gezeigt und in bit(32)
umgewandelt . Beispiel mit 7 Hex-Ziffern und int
oder 8 Ziffern und bigint
:
SELECT ('x'|| 'deafbee')::bit(28)::int
, ('x'|| 'deadbeef')::bit(32)::bigint;
int4 | int8
-----------+------------
233503726 | 3735928559
bigint
für max. 16 Hexadezimalziffern
Bis zu 16 Hexadezimalziffern können in bit(64)
umgewandelt werden und dann zu bigint
gezwungen (int8
, 8-Byte Integer) - in der oberen Hälfte wieder in negative Zahlen überlaufend:
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 Hexadezimalziffern
Die Postgres-uuid
Datentyp ist kein numerischer Typ . Aber es ist der effizienteste Typ in Standard-Postgres, um bis zu 32 Hexadezimalziffern zu speichern und nur 16 Byte Speicherplatz zu belegen. Es gibt eine Direktbesetzung aus text
zu uuid
(keine Notwendigkeit für bit(n)
als Wegpunkt), sondern genau 32 Hexadezimalziffern sind erforderlich.
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
Wie Sie sehen können, ist die Standardausgabe eine Zeichenfolge aus Hexadezimalziffern mit typischen Trennzeichen für UUID.
md5-Hash
Dies ist besonders nützlich, um md5-Hashes zu speichern :
SELECT md5('Store hash for long string, maybe for index?')::uuid AS md5_hash;
md5_hash
--------------------------------------
02e10e94-e895-616e-8e23-bb7f8025da42
Siehe:
- Was ist der optimale Datentyp für ein MD5-Feld?