MySQL中&、|返回0或NULL主因是操作数类型不匹配:字符串转整数规则脆弱(空串/非数字开头均变0),NULL参与位运算恒得NULL;须确保操作数为整型并用COALESCE处理NULL。

MySQL 的 & 和 | 运算符为什么返回 0 或 NULL?
直接用 &、| 做位运算时结果异常,大概率是操作数类型不匹配。MySQL 会把字符串或 NULL 隐式转成整数,但转换规则很“脆”:空字符串变 0,非数字开头的字符串也变 0,而 NULL 参与任何位运算都得 NULL。
- 确保两个操作数都是整型(
TINYINT、INT等),别用VARCHAR存标志位 - 查数据前先
SELECT column + 0看是否能转出数字,避免隐式转换踩坑 - 用
COALESCE(column, 0)拦住NULL,否则整个表达式失效
PostgreSQL 怎么用 bit_and() 聚合多行位标志?
MySQL 没这个聚合函数,但 PostgreSQL 有,适合统计权限集合交集——比如“所有用户都开启的开关”。注意它只接受 BIT 类型,不是整数;想对 INTEGER 字段用,得先转。
- 对整数列聚合:写成
bit_and((flag_col::text)::bit(32))::bigint,长度必须覆盖最大可能值 - 如果某行
flag_col是NULL,默认跳过;但只要全为NULL,结果就是NULL,不是0 - 性能上,
bit_and()无法走索引,大数据量慎用,优先考虑预计算或应用层合并
SQL Server 的 ^(异或)常被误当成“取反”,怎么安全判断权限变更?
^ 是异或,不是按位取反(那是 ~)。常见错误是想“找出新旧权限差异”,却写成 old_flags ^ new_flags = 1——这只能捕获最低位变化,漏掉其他位。
- 要检测任意位变化:用
(old_flags ^ new_flags) != 0,不等于零就说明至少一位不同 - 要定位具体哪几位变了:结果再和原值
&,比如(old_flags ^ new_flags) & old_flags得到被关闭的位 - SQL Server 中
~对无符号整数行为和 C 不同,负数补码表示下容易溢出,建议统一用INT并限制值范围 ≤ 2147483647
SQLite 的 BITAND() 函数不存在,怎么模拟?
SQLite 3.35+ 才内置 BITAND()、BITOR(),老版本只能手搓。最稳的方式是用 CAST + 字符串拼接 + eval(不推荐),或者改用数学表达式。
- 安全做法:用
(a & b)—— SQLite 支持原生&运算符,但仅限于整数,且要求编译时启用了ENABLE_BITWISE(多数发行版已启用) - 验证是否支持:执行
SELECT 5 & 3;,若返回1就行;若报错 “no such function: BITAND”,说明得升级或换思路 - 实在不行,用
case when (a % 2) = 1 and (b % 2) = 1 then 1 else 0 end手动算最低位,但多位就太累,不如迁移到支持位运算的引擎
位运算本身不难,难的是各数据库对“整数边界”“NULL 传播”“隐式转换”的处理逻辑完全不同。写之前一定先在目标环境里跑个 SELECT 1 & NULL, 1 & '2', ~2147483647; 看结果,比查文档快。










