如何将位掩码应用于MySQL中的整数?

如何将位掩码应用于MySQL中的整数?,mysql,type-conversion,integer,Mysql,Type Conversion,Integer,问题是: 数据库Rx30将处方状态存储在一个名为“Rxstatus”的字段中。它们存储的数字是一个从不大于255的整数。设置的位决定脚本是否已填充 一位代表告诉我们,如果设置了16、32或128,脚本将被视为“未填充” 现在我们需要做的是取一个整数,比如说'49',看看设置了哪些位。为了提高速度,这需要通过MySQL完成。我知道49是: 32+16+1 = 49 因此,此字段中设置了16,因此脚本未填充 如何(在MySQL中)获取一个整数,比如说152,并确定设置了它的哪些位 一旦我们确定设置

问题是:

数据库Rx30将处方状态存储在一个名为“Rxstatus”的字段中。它们存储的数字是一个从不大于255的整数。设置的位决定脚本是否已填充

一位代表告诉我们,如果设置了16、32或128,脚本将被视为“未填充”

现在我们需要做的是取一个整数,比如说'49',看看设置了哪些位。为了提高速度,这需要通过MySQL完成。我知道49是:

32+16+1 = 49
因此,此字段中设置了16,因此脚本未填充

如何(在MySQL中)获取一个整数,比如说152,并确定设置了它的哪些位

一旦我们确定设置了什么,如果设置了16、32或128,我们可以认为脚本未填充并产生正确的结果。

使用类似的
&

select Rxstatus & 2 = 2 as 2_set, 
       Rxstatus & 4 = 4 as 4_set,
       Rxstatus & 8 = 8 as 8_set,
       Rxstatus & 16 = 16 as 16_set,
       Rxstatus & 32 = 32 as 32_set,
       Rxstatus & 64 = 64 as 64_set,
       Rxstatus & 128 = 128 as 128_set
from your_table

您可以将数字转换为二进制,这样您就可以看到设置了哪些位

为此,您可以使用,例如,您可以将数字49从十进制转换为二进制,如下所示:

SELECT CONV(49,10,2);

产生
110001

如果您有测试位掩码,例如
32+16+1=49
,并且您想知道是否在
Rxstatus
中设置了其中任何一个,您可以使用:

SELECT Rxstatus & 49 != 0
SELECT Rxstatus & 49 = 49
如果您想知道是否已全部设置,请使用:

SELECT Rxstatus & 49 != 0
SELECT Rxstatus & 49 = 49
要设置位掩码中的所有位,请执行以下操作:

UPDATE Rx30
SET Rxstatus = Rxstatus | 49
WHERE <condition>
UPDATE Rx30
SET Rxstatus = Rxstatus & ~49
WHERE <condition>
更新Rx30
设置Rxstatus=Rxstatus | 49
哪里
要取消设置位掩码中的所有位,请执行以下操作:

UPDATE Rx30
SET Rxstatus = Rxstatus | 49
WHERE <condition>
UPDATE Rx30
SET Rxstatus = Rxstatus & ~49
WHERE <condition>
更新Rx30
设置Rxstatus=Rxstatus&~49
哪里

在回顾了这里的一些答案并与一些同事讨论后,我们通过检查转换后的长度得到了正确的结果:

LENGTH( CONV( Rxstatus, 10, 2 ) ) NOT IN ( 5, 6, 8 ))
例如,我们使用字段的长度来确定是否设置了数字。如果字段中设置了5、6或8,则必须存在16、32或128

10000    (Length 5, = 16)
100000   (Length 6, = 32)
10000000 (Length 8, = 128)
只是长度本身给了我们必须设置的值。感谢你们在短短30分钟内帮助我解决了这个问题


查询在0.23秒内运行了460000多个字段:D

您可能是指从一个字节转换而来,因为一个字节甚至不能高于1:)是的,我知道,很抱歉!你所说的是一种称为位掩码的常见结构。你可以使用MySQL的,即按位和16、32或128。这是一种脆弱的方法。具体来说,如果设置了位7,则长度将为7。因此,您的测试将返回false。不幸的是,如果设置了位7,即使也设置了位6,它也将返回false-在这种情况下,它应该返回true。阅读本文的任何人都应该使用一个“位屏蔽”答案,说明如何使用“&”提取/测试所需位。未来的读者:不要使用
CONV
。在查看了(脆弱的)被接受的答案后,我发现使用
CONV
是一个错误。因为返回字符串的长度会随数字的不同而变化,所以很难找到特定的位。改用位屏蔽-参见上面的其他答案。为什么会很难?如果您想知道第4位,并且字符串的长度为3,那么这就意味着它是0。这很困难,因为字符串长度将根据值的大小而变化。考虑范围从0到255的值。CONV将返回长度从1到8的字符串。现在,编写一个简单的公式来测试值为16的位。这是一个混乱-你必须处理8个不同的字符串长度。可能,但不实用。(这也是低效的,因为你要把一个数字转换成一个字符串,然后从字符串中提取一个字符。但这不是一个重要的问题。)现在试着测试多个位。与顶级方法相比:
选择Rxstatus&176!=0
。要澄清所问的特定问题:OP询问如何知道是否设置了“16、32或128”中的任何一个。这些的总和是“176”,因此对他来说,解决方案是
selectrxstatus&176!=0
。或者,为了更容易查看正在测试的位,请以二进制形式提供测试值:
SELECT Rxstatus&b'10110000'!=0
。。。。或者,如果您更喜欢使用位值的十进制表示:
选择Rxstatus&(128 | 32 | 16)!=0