状态中的位标志。查找一个标志= 0的状态

时间:2013-12-27 14:43:28

标签: php mysql bit-manipulation

假设我在状态中有三位标志,以整数存储在mysql中

Approved    Has Result    Finished
0|1         0|1           0|1

现在我想找到状态为的行:Finished = 1,Has Result = 1和Approved = 0.

然后是数据:

0 "000"
1 "001"
3 "011"
7 "111"

应该产生

false
false
true
false

我能做点什么吗? (在mysql中)

status & "011" AND ~((bool) status & "100")

无法弄清楚如何查询“已批准= 0”。

或者我应该完全放弃使用位标志,并将它们分成不同的列?

使用位标志的原因部分是为了mysql性能。

2 个答案:

答案 0 :(得分:2)

当我开始编程时,我喜欢做的事情是使用2的幂作为标志,因为缺少布尔或位类型:

const FINISHED = 1;
const HAS_RESULT = 2;
const APPROVED = 4;

然后你可以这样检查:

$status = 5; // 101
if ($status & FINISHED) { 
    /*...*/ 
}

修改

让我对此进行扩展:

  

无法弄清楚如何查询“已批准= 0”。

     

或者我应该完全放弃使用位标志,并将它们分成不同的列?

     

使用位标志的原因部分是为了mysql性能。

问题是,您没有使用按位标志。您正在使用一个“模拟”按位标志的字符串,这使得实际执行正确的标记检查变得困难。您必须将其转换为按位表示,然后进行检查。

将标志值存储为整数,并声明您将用于执行检查的标志标识符。 TINYINT应该为您提供7个可能的标志(减去用于符号的最高有效位)和无符号TINYINT 8可能的标志。

答案 1 :(得分:2)

使用整数而不是二进制文本。而不是011,请使用3

要获得批准的行:

SELECT
    *
FROM
    `foo`
WHERE
    (`status` & 4)

或已批准和已完成的行:

SELECT
    *
FROM
    `foo`
WHERE
    (`status` & 5)

或已完成但未被接受:

SELECT
    *
FROM
    `foo`
WHERE
    (`status` & 1)
AND
    (`status` ^ 4)

已完成= 1,结果= 1且已批准= 0 ”可能与status = 3一样简单。