在 C# 中的 VARBINARY 上匹配 SQL 服务器模数

Matching SQL Server Modulo on a VARBINARY in C#

前段时间,我们在 ufn_GroupData 示例函数中实现了这种 Optimizing Protected Indexes 方法的细微变化,从 SQL Server Central 到索引加密数据:

CREATE FUNCTION [dbo].[fncGetBucket]    
(  
    @String NVARCHAR(3500) 
) 
RETURNS INT   
AS
BEGIN  
    DECLARE @Result INT = NULL;  
    IF @String IS NOT NULL
        SET @Result = HASHBYTES('SHA2_256', @String) % 20000;  
    RETURN @Result;   
END

使用此 UDF 的结果作为“分桶”索引,几百万行愉快地存储在数据库中。

现在我们希望能够在 C# 中生成匹配的存储桶值,上面看似简单的 SQL 并没有说明如何做到这一点。

事实上,我发现很难开始。但我可以说这段代码:

byte[] encoded = SHA256.Create().ComputeHash(Encoding.Unicode.GetBytes(str));

生成与 HASHBYTES 相同的散列,因此我已经完成了第一步。

那么 SQL 实际上用那个模运算符做了什么???

感谢所有帮助!

HASHBYTES('SHA2_256') returns 一个 32 字节的 ByteArray

内部发生的事情是

cast(HASHBYTES('SHA2_256', @String) as int) % 20000

所以这里有一个整数溢出,被 SQL 服务器优雅地忽略了。
这是未定义的行为并且不容易转换为 C#。

你可以通过取最后 4 个字节和 modulo 那些来实现类似的东西。
这似乎适用于您的 mod 20000。

byte[] encoded = SHA256.Create().ComputeHash(Encoding.UTF8.GetBytes("asdf"));

var last4Bytes = encoded.Skip(28).Take(4).Reverse().ToArray();
var myInt = BitConverter.ToInt32(last4Bytes);
var moduloResult = myInt % 20000;

这给了我与

相同的结果
print HASHBYTES('SHA2_256', 'asdf') % 20000

12635