Sql 修复错误的“位”

Sql 修复错误的“位”,sql,sql-server,bit-manipulation,Sql,Sql Server,Bit Manipulation,我试图修复一个列中的数据,该列在int列中存储了大量位标志 所发生的事情是在某个地方,设置了一个错误的标志6,因此我需要准备一个脚本来修复受影响的记录 我尝试过执行一些查询来提取看起来错误的数据,但这是基于假设的,我想知道是否有更聪明的方法 一些事实: 应该设置的位是8,但使用了6 该列当前最多存储23位,以表示有花园/有家具/有房子/停车场等的物业的开/关状态 有些记录受到影响,有些则没有 考虑到位6是无效的,我能做些聪明的事情来根据这个事实提取这些记录吗?我假设你在这里讨论的是位掩蔽 基于这

我试图修复一个列中的数据,该列在int列中存储了大量位标志

所发生的事情是在某个地方,设置了一个错误的标志6,因此我需要准备一个脚本来修复受影响的记录

我尝试过执行一些查询来提取看起来错误的数据,但这是基于假设的,我想知道是否有更聪明的方法

一些事实:

应该设置的位是8,但使用了6 该列当前最多存储23位,以表示有花园/有家具/有房子/停车场等的物业的开/关状态 有些记录受到影响,有些则没有
考虑到位6是无效的,我能做些聪明的事情来根据这个事实提取这些记录吗?

我假设你在这里讨论的是位掩蔽


基于这种假设,我认为您不能仅仅查询数据以获得修复。位屏蔽的工作方式是将所有位的值相加。将二进制文件转换为整数,以便将以下掩码:1001存储为9

如果使用6而不是8,则与同时设置4位和2位相同。因此,您的查询将返回4位和2位为on的所有有效记录


使用相同的示例,如果您意外地使用了6而不是8,那么1001将变为7,但是您如何将其与0111区分开来,0111将正确地伪装为7?

您可以使用以下方法来实现:

set nocount on;

declare @test table (id int identity primary key, bits int);

insert into @test values(63);
insert into @test values(1);

select id, cast(bits as binary(4)) as 'bits' 
from @test;

update @test
set bits = (bits & 8388575) | 128
where (bits & 32) <> 0;

select id, cast(bits as binary(4)) as 'bits' 
from @test;

/*
Outputs

id          bits
----------- ----------
1           0x0000003F
2           0x00000001

id          bits
----------- ----------
1           0x0000009F
2           0x00000001

*/

所以当你用6二进制0110屏蔽时,你设置了位2和3,就像你用4和2屏蔽一样

所以,您所能做的就是检查设置了这些位的行。这些将是受影响的行-但是,其中一些行可能已经设置了这些位。您必须手动完成,或者以某种方式缩小数据集。也许设置某些位的组合是无效的

此查询将获得已用6屏蔽的行列表:

select * from table where bitfield & 6 = 6

请注意,在处理32位有符号值时,位31可能会出现问题。否则:

-- Check each bit in an integer.
declare @Sample as Int = 6;
with Bits as (
  select Cast( 1 as BigInt ) as BitMask, 0 as BitPosition
  union all
  select Bitmask * 2, BitPosition + 1
    from Bits
    where BitPosition < 31 )
  select BitPosition, BitMask,
    case when Cast( @Sample as BigInt ) & BitMask <> 0 then 'Set' else 'Clear' end as State
    from Bits;

-- Play with some sample data in a table.
declare @Samples as Table ( SampleId Int Identity, Number Int );
insert into @Samples ( Number ) values ( 0 ), ( 1 ), ( 2 ), ( 3 ), ( 30 ), ( 65 ), ( 16385 );
select * from @Samples;

-- Clear bit 6 in each row.
update @Samples
  set Number &= 2147483647 - Power( 2, 6 );
select * from @Samples;

-- Set bit 6 in each row.
update @Samples
  set Number |= Power( 2, 6 );
select * from @Samples;

-- Clear bit 6 in each row again.
update @Samples
  set Number &= 2147483647 - Power( 2, 6 );
select * from @Samples;

也许它涉及到使用余数的东西?拉取列中的所有有效位,如果有余数,那就是受影响的记录?你是说位6被设置了,还是说字段被设置为6?也就是说,你是说位6 2^6=64被设置了,还是字段被6屏蔽而不是8试图设置位3^3=8?@Blorgbeard 6被屏蔽而不是8,试图设置位3。也许,但是数据的存储方式是,如果值上的位1、4和32被存储为37。我明白了,所以如果列值中有一个有效位,那么您可以使用您的建议减去有效位,然后查看是否有余数。我不认为您确实能够查询数据以获得修复,这根魔杖必须留在抽屉里。我会把它吸起来,然后手动修复数据。谢谢你的时间。谢谢你,我会拿走非常有用的比特生成器cte,这是我在理解比特时发现的非常宝贵的东西。