Ответ 1
Вы можете использовать агрегат CHECKSUM_AGG. это сделано для этой цели.
Есть ли способ в 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% медленнее при обработке повторяющихся данных.
Большое спасибо
Вы можете использовать агрегат 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;