2012-08-08 23 views
12

Có cách nào trong SQL Server 2012 để tạo ra một băm của một tập hợp các hàng và cột không?Tạo một băm cho một tập hợp các hàng trong máy chủ sql

Tôi muốn tạo băm, lưu nó vào bản ghi gốc. Khi cập nhật đến, tôi sẽ so sánh băm đến với băm bản ghi gốc và tôi sẽ biết liệu dữ liệu đã thay đổi hay chưa.

Vì vậy, một cái gì đó như thế này sẽ được tốt đẹp:

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

"CONCATENATE" sẽ là một chức năng tổng hợp mà sẽ không chỉ concat các cột, nhưng cũng có thể, các hàng bên trong resultset. Giống như MAX, nhưng trả lại mọi thứ dưới dạng chuỗi nối.

Hy vọng điều này giúp bạn hiểu ý tôi là gì!

Vấn đề cơ bản mà tôi đang cố gắng giải quyết là hệ thống của khách hàng của tôi thực hiện nhập một lượng lớn dữ liệu phân cấp. Nếu tôi có thể tránh việc xử lý thông qua việc sử dụng băm, thì tôi nghĩ điều này sẽ tiết kiệm rất nhiều thời gian. Hiện tại, SP đang chạy chậm hơn 300% khi xử lý dữ liệu trùng lặp.

Rất cám ơn

Trả lời

10

Bạn có thể sử dụng CHECKSUM_AGG tổng hợp. nó được làm cho mục đích đó.

+4

Thật không may CHECKSUM đã biết những điểm yếu (tức là xung đột thực tế). Ví dụ. loại thập phân http://sqlserverpains.blogspot.com.au/2008/06/checksum-pains.html vì vậy hãy cẩn thận. – Shiv

1

Đối băm hàng duy nhất:

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

cho bảng checksum:

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

Liệu này tạo ra một băm từ toàn bộ resultset? Hoặc nó sẽ sản xuất nhiều băm, một cho mỗi hàng trong MyChildTable? – krisdyson

+0

thử giải pháp thứ 2 trong bản chỉnh sửa của tôi. –

+0

Tôi đã cập nhật lại để ngăn chặn tràn số nguyên. –

1

Một cách tiếp cận:

-- 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; 
9
select HashBytes('md5',convert(varbinary(max),(SELECT * FROM MyChildTable WHERE ParentId = 2 FOR XML AUTO))) 

nhưng HashBytes được giới hạn chỉ 8000 bytes ... bạn có thể làm cho một chức năng để có được de MD5 cho mỗi 8000 byte ....

+0

Nếu bạn đang sử dụng SQL Server 2016 trở lên, có hỗ trợ JSON, tôi khuyên bạn nên sử dụng 'FOR JSON AUTO' thay vì' FOR XML AUTO', vì điều này có vẻ nhanh hơn gấp 2 lần trong một vài thử nghiệm mà tôi đã làm. – Isak

Các vấn đề liên quan