Начини без динамичен SQL
В text
няма прехвърляне от шестнадесетични числа представяне до числов тип, но можем да използваме bit(n)
като пътна точка. Иманедокументирани предава от битови низове (bit(n)
) към целочислени типове (int2
, int4
, int8
) - вътрешното представяне е двоично съвместимо. Цитирам Том Лейн:
Това разчита на някакво недокументирано поведение на преобразувателя на входен тип бит, но не виждам причина да очаквам, че това ще се счупи. Вероятно по-голям проблем е, че изисква PG>=8.3, тъй като преди това не е имало прехвърляне на текст към битове.
integer
за макс. 8 шестнадесетични цифри
До 8 шестнадесетични цифри могат да бъдат преобразувани в bit(32)
и след това принуден към integer
(стандартно 4-байтово цяло число):
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 използва подписан тип цяло число, така че шестнадесетичните числа над '7fffffff'
преливане в отрицателно цяло число числа. Това все още е валидно, уникално представяне, но значението е различен. Ако това има значение, превключете към bigint
; вижте по-долу.
За повече от 8 шестнадесетични цифри най-малко значимите знаци (излишни вдясно) се съкратяват .
4 бита в битов низ кодира 1 шестнадесетична цифра . Шестнадесетични числа с известна дължина могат да бъдат прехвърлени към съответния bit(n)
директно. Като алтернатива, въведете шестнадесетични числа с неизвестна дължина с водещи нули (0
) както е демонстрирано и прехвърлено към bit(32)
. Пример със 7 шестнадесетични цифри и int
или 8 цифри и bigint
:
SELECT ('x'|| 'deafbee')::bit(28)::int
, ('x'|| 'deadbeef')::bit(32)::bigint;
int4 | int8
-----------+------------
233503726 | 3735928559
bigint
за макс. 16 шестнадесетични цифри
До 16 шестнадесетични цифри могат да бъдат преобразувани в bit(64)
и след това принуден да bigint
(int8
, 8-байтово цяло число) - отново преливане в отрицателни числа в горната половина:
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
за макс. 32 шестнадесетични цифри
Postgres uuid
типът данни не е числов тип . Но това е най-ефективният тип в стандартния Postgres за съхраняване на до 32 шестнадесетични цифри, заемащи само 16 байта място за съхранение. Имадиректно предаване от text
към uuid
(няма нужда от bit(n)
като точка), но точно Необходими са 32 шестнадесетични цифри.
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
Както можете да видите, стандартният изход е низ от шестнадесетични цифри с типични разделители за UUID.
md5 хеш
Това е особено полезно за съхраняване на md5 хешове :
SELECT md5('Store hash for long string, maybe for index?')::uuid AS md5_hash;
md5_hash
--------------------------------------
02e10e94-e895-616e-8e23-bb7f8025da42
Вижте:
- Кой е оптималният тип данни за поле MD5?