BIT_AND和BIT_OR仅用于分组聚合多行权限交集或并集,不可用于单用户权限判断;单行校验必须用&运算符,且二者必须配合GROUP BY使用,否则报错。

BIT_AND 和 BIT_OR 不是用来查“某个用户有没有权限”的,它们只在统计多行数据的共性或并集时才有效;单行权限判断必须用 & 运算符。
BIT_AND/BIT_OR 必须配合 GROUP BY 使用
这两个函数是聚合函数,不是过滤工具。写成 WHERE BIT_AND(perm_mask) = 4 会直接报错:Invalid use of group function。
- 只能出现在
SELECT或HAVING子句中,且必须有对应GROUP BY - 典型正确写法:
SELECT role_id, BIT_AND(perm_mask) FROM role_perms GROUP BY role_id - 想筛选“全员都开启删除权限(bit 2,值为 4)”的组,得写:
HAVING BIT_AND(COALESCE(perm_mask, 0)) & 4 = 4
NULL 值会让整组结果变 NULL,必须用 COALESCE 拦住
只要分组内任意一行 perm_mask 是 NULL,BIT_AND 或 BIT_OR 的结果就是 NULL,导致后续条件(如 & 4 = 4)无法成立。
- 错误写法:
BIT_AND(perm_mask) & 4 = 4—— 遇到 NULL 就失效 - 正确写法:
BIT_AND(COALESCE(perm_mask, 0)) & 4 = 4—— 把 NULL 视为 0,不影响位交集逻辑 - 全 NULL 组经
COALESCE后变成全 0,BIT_AND结果为 0,语义清晰可预期
单用户权限检查别用 BIT_AND/BIT_OR,用 & 运算符
生产环境里 95% 的权限校验根本不会出现 BIT_AND,而是直接在 WHERE 中用 & 判断掩码位是否置位。
- 查“用户是否有删除权限(bit 2 = 4)”:
WHERE (perm_mask & 4) = 4—— 括号不能省,因为&优先级低于= - 查“同时有读(bit 0 = 1)和写(bit 1 = 2)”:
WHERE (perm_mask & 3) = 3(因为1 | 2 = 3) - 查“有读或删除权限(至少一个)”:
WHERE (perm_mask & 5) != 0(5 = 1 | 4)
性能与兼容性:别指望走索引,也别跨数据库硬搬
BIT_AND/BIT_OR 在 MySQL 8.0.17+ 原生支持,但 PostgreSQL、SQL Server、Oracle 均无等价内置函数;且这类聚合无法利用索引加速,大数据量分组延迟明显。
- MySQL 5.7 及更早版本不支持,需用变量模拟(不稳定,慎用)
- PostgreSQL 要么用
int8or(),要么转bit(n)类型再调bit_or(),写法完全不同 - 单行
&查询可配合生成列 + 索引优化,而聚合位运算是纯计算密集型操作
真正容易被忽略的是:BIT_AND 返回某一位为 1,要求该组**所有非 NULL 行**在该位上都是 1 —— 这个“全量一致”的语义,和日常说的“多数人有权限”完全不是一回事;一旦误读,权限策略就可能从“最小权限”滑向“过度放权”。

















