我们对sql server中的一些数据进行校验,如下:
declare @cs int;
select
@cs = CHECKSUM_AGG(CHECKSUM(someid, position))
from
SomeTable
where
userid = @userId
group by
userid;
然后与客户共享此数据。我们希望能够在客户端重复校验和......但是似乎没有关于如何计算上述函数中的校验和的任何信息。任何人都可以启发我吗?
我们对sql server中的一些数据进行校验,如下:
declare @cs int;
select
@cs = CHECKSUM_AGG(CHECKSUM(someid, position))
from
SomeTable
where
userid = @userId
group by
userid;
然后与客户共享此数据。我们希望能够在客户端重复校验和......但是似乎没有关于如何计算上述函数中的校验和的任何信息。任何人都可以启发我吗?
CHECKSUM 函数不能提供质量非常好的校验和,而且 IMO 对于大多数用途来说毫无用处。据我所知,该算法尚未发布。如果您想要检查您是否可以复制自己,请使用 HashBytes 函数和标准的已发布算法之一,例如 MD5 或 SHA。
//SQL和C#镜像乌克兰的快速哈希和
private Int64 HASH_ZKCRC64(byte[] Data)
{
Int64 Result = 0x5555555555555555;
if (Data == null || Data.Length <= 0) return 0;
int SizeGlobalBufer = 8000;
int Ost = Data.Length % SizeGlobalBufer;
int LeftLimit = (Data.Length / SizeGlobalBufer) * SizeGlobalBufer;
for (int i = 0; i < LeftLimit; i += 64)
{
Result = Result
^ BitConverter.ToInt64(Data, i)
^ BitConverter.ToInt64(Data, i + 8)
^ BitConverter.ToInt64(Data, i + 16)
^ BitConverter.ToInt64(Data, i + 24)
^ BitConverter.ToInt64(Data, i + 32)
^ BitConverter.ToInt64(Data, i + 40)
^ BitConverter.ToInt64(Data, i + 48)
^ BitConverter.ToInt64(Data, i + 56);
if ((Result & 0x0000000000000080) != 0)
Result = Result ^ BitConverter.ToInt64(Data, i + 28);
}
if (Ost > 0)
{
byte[] Bufer = new byte[SizeGlobalBufer];
Array.Copy(Data, LeftLimit, Bufer, 0, Ost);
for (int i = 0; i < SizeGlobalBufer; i += 64)
{
Result = Result
^ BitConverter.ToInt64(Bufer, i)
^ BitConverter.ToInt64(Bufer, i + 8)
^ BitConverter.ToInt64(Bufer, i + 16)
^ BitConverter.ToInt64(Bufer, i + 24)
^ BitConverter.ToInt64(Bufer, i + 32)
^ BitConverter.ToInt64(Bufer, i + 40)
^ BitConverter.ToInt64(Bufer, i + 48)
^ BitConverter.ToInt64(Bufer, i + 56);
if ((Result & 0x0000000000000080)!=0)
Result = Result ^ BitConverter.ToInt64(Bufer, i + 28);
}
}
byte[] MiniBufer = BitConverter.GetBytes(Result);
Array.Reverse(MiniBufer);
return BitConverter.ToInt64(MiniBufer, 0);
#region SQL_FUNCTION
/* CREATE FUNCTION [dbo].[HASH_ZKCRC64] (@data as varbinary(MAX)) Returns bigint
AS
BEGIN
Declare @I64 as bigint Set @I64=0x5555555555555555
Declare @Bufer as binary(8000)
Declare @i as int Set @i=1
Declare @j as int
Declare @Len as int Set @Len=Len(@data)
if ((@data is null) Or (@Len<=0)) Return 0
While @i<=@Len
Begin
Set @Bufer=Substring(@data,@i,8000)
Set @j=1
While @j<=8000
Begin
Set @I64=@I64
^ CAST(Substring(@Bufer,@j, 8) as bigint)
^ CAST(Substring(@Bufer,@j+8, 8) as bigint)
^ CAST(Substring(@Bufer,@j+16,8) as bigint)
^ CAST(Substring(@Bufer,@j+24,8) as bigint)
^ CAST(Substring(@Bufer,@j+32,8) as bigint)
^ CAST(Substring(@Bufer,@j+40,8) as bigint)
^ CAST(Substring(@Bufer,@j+48,8) as bigint)
^ CAST(Substring(@Bufer,@j+56,8) as bigint)
if @I64<0 Set @I64=@I64 ^ CAST(Substring(@Bufer,@j+28,8) as bigint)
Set @j=@j+64
End;
Set @i=@i+8000
End
Return @I64
END
*/
#endregion
}
我想出了CHECKSUM
算法,至少对于 ASCII 字符。我在 JavaScript 中创建了一个证明(参见https://stackoverflow.com/a/59014293/9642)。
简而言之:向左旋转 4 位并按每个字符的代码异或。诀窍是找出“异或码”。这是这些表:
var xorcodes = [
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31,
0, 33, 34, 35, 36, 37, 38, 39, // !"#$%&'
40, 41, 42, 43, 44, 45, 46, 47, // ()*+,-./
132, 133, 134, 135, 136, 137, 138, 139, // 01234567
140, 141, 48, 49, 50, 51, 52, 53, 54, // 89:;<=>?@
142, 143, 144, 145, 146, 147, 148, 149, // ABCDEFGH
150, 151, 152, 153, 154, 155, 156, 157, // IJKLMNOP
158, 159, 160, 161, 162, 163, 164, 165, // QRSTUVWX
166, 167, 55, 56, 57, 58, 59, 60, // YZ[\]^_`
142, 143, 144, 145, 146, 147, 148, 149, // abcdefgh
150, 151, 152, 153, 154, 155, 156, 157, // ijklmnop
158, 159, 160, 161, 162, 163, 164, 165, // qrstuvwx
166, 167, 61, 62, 63, 64, 65, 66, // yz{|}~
];
需要注意的主要是对字母数字的偏见(它们的代码相似且升序)。无论大小写,英文字母都使用相同的代码。
我没有测试过高代码 (128+) 和 Unicode。