首页 > 解决方案 > 如何在 MySQL 中检查 BIT 数据类型?

问题描述

我在users表中有一个名为permissions. 像这样:

// users
+---------+-----------------+-------------+
|   id    | permissions     |    name     |
+---------+-----------------+-------------+
| int(11) | bit(15)         | varchar(20) |
+---------+-----------------+-------------+
| 1       | 001100001111101 | Jack        |
| 2       | 111111111111111 | Peter       |
| 3       | 110000000111011 | Martin      |
+---------+-----------------+-------------+

如您所见,permissions列具有bit(15)数据类型。该值的每一位都决定了一个用户能力。例如,第一位指的是voting-ability,第二位指的是commenting-ability ant等...

我也有一个触发器BEFORE UPDATE,可以像这样调查该权限:

SELECT permissions INTO @deleting_permission FROM users WHERE id = new.deleter_id;

IF old.deleted <> new.deleted THEN
IF (IFNULL((@deleting_permission & b'10000000000' > 0), 0) < 1) THEN
    SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = "You cannot delete post";
END IF;
END IF;

它总是抛出:

你不能删除帖子

即使对于具有权限值的#2 用户也是如此。111111111111111那么有什么问题呢?


注意到我permissions像这样更新列:

-- To give some specific accesses (permissions) to the user
UPDATE users SET permissions = b'111111000101011' WHERE id = ?

-- To give full access (permissions) to the user
UPDATE users SET permissions = -1 WHERE id = ?

标签: mysqlsqlbit

解决方案


如果要使用该BIT类型,则需要使用按位运算符,而不是常规运算符。例如,如果您想检查用户是否将最左边的位设置为权限,您可以执行以下&操作:

SELECT permissions INTO @p FROM users WHERE id = new.deleter_id;


IF old.deleted <> new.deleted THEN
    IF (b'100000000000000' & @p = 0)
    THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = "You cannot delete post";
    END IF;
END IF;

上面的基本思想是,文字b'100000000000000'用作掩码,可用于检测最左边的位(并且只有该位)是否设置为 1。如果设置为 1,则&操作不会返回 0。

具有权限的用户111111111111111拥有所有权限的原因是任何掩码检查位都会返回 true。


推荐阅读