Cara tanpa SQL dinamis
Tidak ada pemeran dari angka heksa di text
representasi ke tipe numerik, tetapi kita dapat menggunakan bit(n)
sebagai titik jalan. Ada yang tidak berdokumen dilemparkan dari string bit (bit(n)
) ke tipe integer (int2
, int4
, int8
) - representasi internal kompatibel dengan biner. Mengutip Tom Lane:
Ini bergantung pada beberapa perilaku tidak terdokumentasi dari konverter input tipe bit, tetapi saya tidak melihat alasan untuk mengharapkan itu akan rusak. Masalah yang mungkin lebih besar adalah bahwa hal itu memerlukan PG>=8.3 karena tidak ada teks untuk bit yang dilemparkan sebelumnya.
integer
untuk maks. 8 digit heksadesimal
Hingga 8 digit hex dapat dikonversi ke bit(32)
dan kemudian dipaksa untuk integer
(integer 4-byte standar):
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 menggunakan tipe integer yang ditandatangani, jadi angka hex di atas '7fffffff'
meluap ke bilangan bulat negatif angka. Ini masih valid, representasi unik tetapi makna berbeda. Jika itu penting, alihkan ke bigint
; lihat di bawah.
Untuk lebih dari 8 digit heksagonal, karakter yang paling tidak signifikan (kelebihan di sebelah kanan) dipotong .
4 bit dalam bit string encode 1 digit hex . Bilangan heksagonal dengan panjang yang diketahui dapat dilemparkan ke masing-masing bit(n)
secara langsung. Atau, pad nomor heksadesimal panjang tidak diketahui dengan nol di depan (0
) seperti yang ditunjukkan dan dilemparkan ke bit(32)
. Contoh dengan 7 digit hex dan int
atau 8 digit dan bigint
:
SELECT ('x'|| 'deafbee')::bit(28)::int
, ('x'|| 'deadbeef')::bit(32)::bigint;
int4 | int8
-----------+------------
233503726 | 3735928559
bigint
untuk maks. 16 digit heksadesimal
Hingga 16 digit hex dapat dikonversi ke bit(64)
dan kemudian dipaksa untuk bigint
(int8
, bilangan bulat 8-byte) - meluap ke angka negatif di bagian atas lagi:
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
untuk maks. 32 digit heksadesimal
Postgres uuid
tipe data bukan tipe numerik . Tapi ini adalah tipe Postgres standar yang paling efisien untuk menyimpan hingga 32 digit hex, hanya menempati 16 byte penyimpanan. Ada pemeran langsung dari text
ke uuid
(tidak perlu bit(n)
sebagai titik jalan), tetapi tepatnya 32 digit heksa diperlukan.
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
Seperti yang Anda lihat, keluaran standar adalah string digit heksagonal dengan pemisah khas untuk UUID.
hash md5
Ini sangat berguna untuk menyimpan hash md5 :
SELECT md5('Store hash for long string, maybe for index?')::uuid AS md5_hash;
md5_hash
--------------------------------------
02e10e94-e895-616e-8e23-bb7f8025da42
Lihat:
- Apa tipe data optimal untuk bidang MD5?