2014-07-11 64 views
1

像这个问题,这里是问题摘要: 我有480种不同的钢种。一些钢可以通过加热和/或化学处理转化成另一种钢。而且,多年来,规范和技术发生了变化,一些突变变得不可能,其他突变也变得可用我的生产环境需要自由而轻松地添加或删除单个钢种,因为他们在db中搜索它们。如何在长二进制值(超过64位)上执行二进制压缩

解决方案:我想使用位掩码来提供解决方案。每种钢材类型都会分配一个有意义的位置。可以放在一起的钢种可以将他们的位掩码组合起来,从而创建默认的组搜索掩码。由于在运行时使用修改组,所以个别钢种的位掩码将被添加或从默认组搜索掩码中减去。执行时,查询将对指定表中所有项目的各个位掩码执行二进制“与”运算,并返回所有内容,如searchMask & individualMask <> 0我成功将此原则用于其他应用程序,但SQL中的位运算符不能应用于一对二进制字段。我可以使用的最大数据类型是64位bigint。

因此,如何在T-SQL中的两个二进制字段上执行二进制与操作,或者我可以在不创建任意组的情况下使用其他解决方案来解决上述问题?

+0

考虑用于对varbinary值进行操作的SQL CLR数据类型或函数。有了这个策略,你无论如何都无法有效地进行索引 – usr

回答

1

一个想法可以是分割在64位的组块中的掩模,并检查每两chunck分开然后添加按位操作的结果,概念的证明可以转换到一个功能是

DECLARE @a VARBINARY(200) = Cast(Replicate(Char(128), 200) AS VARBINARY(200)) 
DECLARE @b VARBINARY(200) = Cast(Replicate(Char(130), 200) AS VARBINARY(200)); 

WITH splitter AS (
    SELECT Cast(Cast(LEFT(@a, 64) AS VARBINARY(64)) AS BIGINT) a 
     , Cast(Cast(LEFT(@b, 64) AS VARBINARY(64)) AS BIGINT) b 
     , _and = Cast(0 AS BIT) 
     , b = 1 
     , rev = Cast(Ceiling(Len(@a)/64.0) AS INT) 
    UNION ALL 
    SELECT Cast(Cast(Substring(@a, b * 64, 64) AS VARBINARY(64)) AS BIGINT) a 
     , Cast(Cast(Substring(@b, b * 64, 64) AS VARBINARY(64)) AS BIGINT) b 
     , _and = _and | Cast(a & b AS BIT), 
     , b = b + 1, 
     , rev = rev - 1 
    FROM splitter 
    WHERE b * 64 < Len(@a) 
) 
SELECT _and | Cast(a & b AS BIT) 
FROM splitter 
WHERE rev = 1 

递归CTE,用了很多的CAST,产生每64字节一行,并执行按位AND前面的两个块时,CASTBIT是要确保该值可以在类型空间补充说,使用按位OR,因为BIT无法相加。

该代码假定这两个值具有相同的维度,如果相反是真的@a应该是较短的一个,以减少迭代在递归CTE