位运算更新前必须确认字段为整数类型;添加权限用 |,撤销用 & ~mask,切换用 ^;不适用于权限继承等复杂关系。
MySQL、PostgreSQL 和 SQL Server 都支持 &、|、^、~ 等位运算符,但前提是目标字段(比如 permissions)必须是整数类型(TINYINT、SMALLINT、INT 或 BIGINT)。如果字段是 VARCHAR 或 JSON,直接用 | 会静默转成 0 或报错(如 MySQL 的 Truncated incorrect INTEGER value)。
常见错误现象:UPDATE users SET permissions = permissions | 4 WHERE id = 123; 执行后值没变——先查 DESCRIBE users; 确认 permissions 类型,再检查是否被 ORM 自动 cast 成字符串。
假设「删除」对应标志位是 8(即 2^3),要开启它,用 |(按位或):它只置 1,不影响其他位。
UPDATE users SET permissions = permissions | 8 WHERE id = 123;5(二进制 101,表示「读+写」),执行后变成 13(1101),新增了第 4 位(从右往左数,位索引从 0 开始)13 | 8 还是 13,安全幂等「编辑」设为 2(2^1),要关掉它,不能用 & 直接和 2,那会清零其他位。正确做法是:先构造掩码(把对应位变 0,其余变 1),再用 &。
掩码 = ~2(在支持符号位的语言里需小心,但主流 SQL 引擎中 ~ 对无符号整数直接按位取反;MySQL 中 ~2 是 18446744073709551613,所以更稳妥写法是显式构造):
UPDATE users SET permissions = permissions & ~2 WHERE id = 123;
~,但注意 ~ 对 INT 返回带符号负数,可用 & 0xFFFFFFFD 替代(0xFFFFFFFD 是 32 位下除第 2 位外全 1)permissions & 2,结果只会剩 0 或 2,其他权限全丢想让「导出」权限(设为 16)翻转(开变关、关变开),用 ^(按位异或)最简洁:
UPDATE users SET permissions = permissions ^ 16 WHERE id = 123;16 → 变 0;原值 0 → 变 16;原值 21(16+4+1)→ 变 5(4+1)真正容易被忽略的是:位运算无法表达「权限继承」「角色叠加」这类关系,它只适合扁平布尔标志集合。一旦权限模型变复杂(比如某功能需同时满足 A 且 B),就得退回到关联表或 JSON 字段,别硬扛。