Создать хэш для набора строк в SQL Server

Есть ли способ в SQL Server 2012 генерировать хэш из набора строк и столбцов?

Я хочу создать хэш, сохранить его в родительской записи. Когда приходит обновление, я сравниваю входящий хеш с хешем родительской записи и узнаю, изменились ли данные.

Так что примерно так было бы неплохо:

SELECT GENERATEHASH(CONCATENATE(Name, Description, AnotherColumn))
FROM MyChildTable WHERE ParentId = 2 -- subset of data belong to parent record 2

"CONCATENATE" - это агрегатная функция, которая объединяет не только столбцы, но и строки в наборе результатов. Как MAX, но возвращает все как конкатенацию строк.

Надеюсь, это поможет вам понять, что я имею в виду в любом случае!

Основная проблема, которую я пытаюсь решить, состоит в том, что система моего клиента выполняет импорт огромного количества иерархических данных. Если я смогу избежать обработки с помощью хэшей, то я думаю, что это сэкономит много времени. В данный момент SP работает на 300% медленнее, когда приходится обрабатывать дублирующиеся данные.

Большое спасибо

4 ответа

Решение

Вы можете использовать агрегат CHECKSUM_AGG. это сделано для этой цели.

select HashBytes('md5',convert(varbinary(max),(SELECT * FROM MyChildTable WHERE ParentId = 2 FOR XML AUTO)))

но HashBytes ограничен только 8000 байтов... вы можете сделать функцию, чтобы получить де Md5 для каждых 8000 байтов....

Для однорядных хэшей:

select HASHBYTES('md5', Name + Description + AnotherColumn)
FROM MyChildTable WHERE ParentId = 2

для контрольной суммы таблицы:

select sum(checksum(Name + Description + AnotherColumn)*1.0)
FROM MyChildTable WHERE ParentId = 2

Другой подход:

-- compute a single hash value for all rows of a table
begin

    set nocount on;

    -- init hash variable
    declare @tblhash varchar(40);
    set @tblhash = 'start';

    -- compute a single hash value
    select @tblhash = sys.fn_varbintohexsubstring(0, hashbytes('sha1',(convert(varbinary(max),@tblhash+
    (select sys.fn_varbintohexsubstring(0,hashbytes('sha1',(convert(varbinary(max),
    -- replace 'select *' if you want only specific columns to be included in the hash calculation
    -- [target table] is the name of the table to calc the hash from
    -- [row_id] is the primary key column within the target table
    -- modify those in the next lines to suit your needs:
    (select * from [target_table] obj2 where obj2.[row_id]=obj1.[row_id] for xml raw)
    ))),1,0))
    ))),1,0)
    from [target_table] obj1;

    set nocount off;

    -- return result
    select @tblhash as hashvalue;

end;
Другие вопросы по тегам