位运算查询需严格遵循括号、整型、索引三原则:where必须写为(role & 4) = 4;视图中应case解包;高频位查建议用生成列+索引。

直接用 & 做掩码检测,但括号不能省、索引基本无效、类型必须是整数——这三点踩错一个,查询就 silently 错或慢得离谱。
WHERE 中用 & 判断某位是否开启,必须加括号
MySQL/SQL Server/PostgreSQL 都支持 & 按位与,但它的运算优先级低于 =。不加括号会导致语义完全错误:
-
WHERE roles & 4 = 4→ 实际被解析为WHERE roles & (4 = 4),即WHERE roles & 1,永远只查 bit 0 - 正确写法只能是:
WHERE (roles & 4) = 4(查第 3 位是否为 1) - 查“有读或写权限”不能写
roles & (1 OR 2)——OR是逻辑运算,不是位或;该用roles & 3 != 0
视图里别裸写 &,用 CASE 解包成布尔别名
在视图中直接暴露 status & 4 = 4 这类表达式,下游难读、难维护、也难调试:
- 推荐写法:
CASE WHEN status & 4 = 4 THEN 1 ELSE 0 END AS is_locked - 这样外部查询可直接写
WHERE is_locked = 1,语义清晰,且避免重复计算 - 注意:PostgreSQL 支持函数索引如
CREATE INDEX ON users ((status & 4)),但 MySQL 不行;别指望is_locked列自动走索引 - 字段若存的是字符串(如
'12'),&会静默转成 0,结果全空——务必确认类型是TINYINT/INT等整型
BIT_AND()、BIT_OR() 只能在 GROUP BY 里用
这些不是单行过滤函数,而是**跨行逐位聚合**工具,常见误用就是塞进 WHERE:
-
WHERE BIT_AND(status) = 1→ 报错Invalid use of group function - 正确场景:统计每类商品的共性状态 →
SELECT cate, BIT_AND(flags) AS common_flags FROM products GROUP BY cate -
BIT_COUNT(roles)是例外,可单独用,比如查用户开了几个权限:SELECT name, BIT_COUNT(roles) FROM users - SQL Server 2022+ 才有
BITAND()兼容函数,老版本只认&;Oracle 必须用BITAND(status, 4),写&直接报ORA-00920
高频查某一位?别硬扛 &,建生成列+索引
哪怕给 roles 加了 B+Tree 索引,WHERE (roles & 8) = 8 依然大概率全表扫描:
- 现实解法一:加物理列
is_premium TINYINT,用触发器或应用层同步更新,再建索引 - 现实解法二(MySQL 5.7+):
ALTER TABLE users ADD COLUMN is_premium TINYINT AS ((roles & 8) = 8) STORED,然后CREATE INDEX idx_is_premium ON users(is_premium) - 注意
STORED关键字不能漏,否则无法索引;BIGINT 字段做位运算时,确保所有掩码值也在 64 位范围内,否则高位截断
位运算本身很快,但一旦和索引、类型、分组语义混在一起,出问题时往往没报错、只返回错数据或慢到超时——最危险的坑,都是静默发生的。










