TSql checksum 比较两个表的数据是否相同

CheckSum函数,用于计算一组表达式的校验和,这个校验和是int,并且对于相同的一组表达式,校验和是相同的,只在极少数情况下,不同的表达式有相同的校验和。CheckSum函数的这一特性,可以用于比较两个表的数据是否相同。如果表中的两列的CheckSum值相同,那么这两列的值是相同的,因此校验和和表达式是一对一的关系。

if object_id(dbo.ta) is not null
    drop table dbo.ta

if object_id(dbo.tb) is not null
    drop table dbo.tb

create table dbo.ta
(c1 int,
c2 varchar(10)
)
create table dbo.tb
( b1 int,
b2 varchar(10)
)

insert into dbo.ta values(1,a),(10,a0),(11,a1),(12,a2),(13,a3),(14,a4)
insert into dbo.tb values(1,a),(10,a0),(11,a1),(12,a2),(13,a3),(14,a4),(15,a5)

--use join clause to compare
select *
from dbo.ta a
left join dbo.tb b
on checksum(c1,c2)=checksum(b1,b2)
where b.b1 is null

select *
from dbo.ta a
right join dbo.tb b
on checksum(c1,c2)=checksum(b1,b2)
where a.c1 is null

--use except clause to compare
select checksum(c1,c2) from dbo.ta
except
select checksum(b1,b2) from dbo.tb

--the query resutl is 1779172094
select checksum(b1,b2) from dbo.tb
except
select checksum(c1,c2) from dbo.ta

--use the value to query 
select * from dbo.tb where checksum(b1,b2)=1779172094

 

MSDN对CheckSum的注释

1,CheckSum函数的语法是:CHECKSUM ( expression [ ,...n ] )

2,Note

CHECKSUM 对其参数列表计算一个称为校验和的哈希值。  此哈希值用于生成哈希索引。 如果 CHECKSUM 的参数为列,并且对计算的 CHECKSUM 值生成索引,则结果是一个哈希索引。 它可用于对列进行等价搜索。

CHECKSUM 满足哈希函数的下列属性:在使用等于 (=) 运算符比较时,如果两个列表的相应元素具有相同类型且相等,则在任何两个表达式列表上应用的 CHECKSUM 将返回同一值。  对于该定义,指定类型的 Null 值被作为相等进行比较。 如果表达式列表中的某个值发生更改,则列表的校验和通常也会更改。 但只在极少数情况下,校验和会保持不变。 因此,我们不推荐使用 CHECKSUM 来检测值是否更改,除非应用程序可以容忍偶尔丢失更改。 请考虑改用 HashBytes。 指定 MD5 哈希算法时,HashBytes 为两个不同输入返回相同结果的可能性比 CHECKSUM 小得多。

表达式的顺序影响 CHECKSUM 的结果值。  用于 CHECKSUM(*) 的列顺序是表或视图定义中指定的列顺序。 其中包括计算列。

CHECKSUM 值取决于排序规则,使用不同排序规则存储的相同值将返回一个不同的 CHECKSUM 值。

3,使用 CHECKSUM 生成哈希索引,通过将计算校验和列添加到索引的表中,然后对校验和列生成索引来生成哈希索引。

-- Create a checksum index
ALTER TABLE Production.Product
ADD cs_Pname AS CHECKSUM(Name);
GO
CREATE INDEX Pname_index ON Production.Product (cs_Pname);
GO

--校验和索引可用作哈希索引,尤其是当要索引的列为较长的字符列时可以提高索引速度。 校验和索引可用于等价搜索。
/*Use the index in a SELECT query. Add a second search 
condition to catch stray cases where checksums match, 
but the values are not the same.*/
SELECT * FROM Production.Product WHERE CHECKSUM(NBearing Ball) = cs_Pname AND Name = NBearing Ball; GO

对计算列创建索引将具体化为校验和列,对 ProductName 值所做的任何更改都将传播到校验和列。 也可以直接对索引的列生成索引。 然而,如果键值较长,则很可能不执行校验和索引甚至常规索引。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。