Добавить в корзинуПозвонить
Найти в Дзене
Oracle APEX

Анти-печенька от Oracle. Hash(CLOB)

Hash функция от CLOB'а дает разные значения. Часто возникает необходимость сравнить два значения. Их можно просто приравнять. Но если это текст, особенно, длинный текст, особенно, хранимый вне базы, то хотелось бы сравнивать не сам исходный материал, а какой-то компактный слепок с него. Равны слепки, - вероятно, равны и оригиналы. Для этого существуют hash функции, вычисляющие конечно-мерное число по произвольной длины аргументу. И наиболее очевидная из них это функция ora_hash(): with tab as
(
select 'Very long text' as txt from dual
union all
select 'Very long text' as txt from dual
)
select txt, ora_hash(txt) from tab
;
Very long text 1372671261
Very long text 1372671261 Здорово! Hash одинаковый, - аргумент, вероятно, тоже одинаковый; наоборот, - соответственно, наоборот. И всё так, пока текст не станет действительно большим и его не придется хранить/представлять в виде CLOB: with tab as
(
select to_clob('Very long text') as txt from dual
union all
select to_clob('Very long text') a

Hash функция от CLOB'а дает разные значения.

Часто возникает необходимость сравнить два значения. Их можно просто приравнять. Но если это текст, особенно, длинный текст, особенно, хранимый вне базы, то хотелось бы сравнивать не сам исходный материал, а какой-то компактный слепок с него. Равны слепки, - вероятно, равны и оригиналы.

Для этого существуют hash функции, вычисляющие конечно-мерное число по произвольной длины аргументу. И наиболее очевидная из них это функция ora_hash():

with tab as
(
select 'Very long text' as txt from dual
union all
select 'Very long text' as txt from dual
)
select txt, ora_hash(txt) from tab
;
Very long text 1372671261
Very long text 1372671261

Здорово! Hash одинаковый, - аргумент, вероятно, тоже одинаковый; наоборот, - соответственно, наоборот.

И всё так, пока текст не станет действительно большим и его не придется хранить/представлять в виде CLOB:

with tab as
(
select to_clob('Very long text') as txt from dual
union all
select to_clob('Very long text') as txt from dual
)
select txt, ora_hash(txt) from tab
;
Very long text
144225892
Very long text
3489913130

Ни-че-го-се-бе!!! Аргумент одинаковый, а hash совершенно разный.

Да, ora_hash() с CLOB'ами работает криво, и в документации это как-то стыдливо обойдено молчанием.

Для действительно актуальной задачи сравнивания двух CLOB'ов приходится применять функцию hash() пакета dbms_crypto, на который следует испросить право исполнения у администратора базы:

with tab as
(
select to_clob('Very long text') as txt from dual
union all
select to_clob('Very long text') as txt from dual
)
select txt, rawtohex(dbms_crypto.hash(txt, 1)) from tab
;
Very long text C463A668E479E5FCE24C784C6D3ECED8
Very long text C463A668E479E5FCE24C784C6D3ECED8

Hash по-разному
Hash по-разному