我正在尝试修复数据,其中一列在int列中存储了多个位标志。
发生了什么事情就行了,设置了错误的标志(6)所以我需要准备一个脚本来修复受影响的记录。
我尝试过执行一些查询来提取看似错误的数据,但这是基于假设的,我想知道是否有更聪明的方法。
一些事实:
8
,但使用了6
考虑到6
位无效,我是否可以根据这一事实将这些记录拉出来?
答案 0 :(得分:1)
我假设你在这里谈论bit masking
。
有了这个假设,我认为您无法仅查询数据以获得修复。 bit masking
的工作方式是将所有位的值相加(即将二进制转换为int),因此以下掩码:1001
将存储为9
如果使用6而不是8,则将4和2位都设置为相同。因此,您的查询将返回4位和2位打开的所有有效记录。
使用相同的示例,如果您不小心使用了6而不是8,那么1001
会变为7,但您如何区别于0111
哪个会被正确屏蔽为7?
答案 1 :(得分:1)
请注意,在处理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;
答案 2 :(得分:0)
您可以使用T-SQL bitwise operators完成此操作,如下所示:
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
*/
答案 3 :(得分:0)
所以当你用6(二进制0110)掩盖时,你已经设置了第2位和第3位 - 好像你用4然后是2来掩盖。
所以你要做的就是检查那些设置的行。那些将是受影响的行 - 但是,其中一些可能已经设置了这些位。您将不得不手动完成,或以某种方式缩小数据集。也许将某些位组合设置无效?
此查询将为您提供已用6:
屏蔽的行列表select * from table where bitfield & 6 = 6