MySQL BIT类型权限校验异常:触发器始终抛出无删除权限错误
问题分析与解决方案
你的触发器始终抛出错误的核心原因是MySQL运算符优先级导致的逻辑错误,另外还有几个需要注意的细节,我来一步步拆解:
1. 运算符优先级的致命问题
在你的触发器条件中:
IFNULL((@deleting_permission & b'10000000000' > 0), 0) < 1
MySQL中,比较运算符(>)的优先级高于位运算符(&),所以这个表达式会被MySQL解析成:
IFNULL((@deleting_permission & (b'10000000000' > 0)), 0) < 1
而b'10000000000'是非零值,所以b'10000000000' > 0的结果是1(布尔值在MySQL中以1/0表示)。最终你实际上是在判断@deleting_permission & 1 > 0——也就是检查权限的最低位(第1位),而不是你想要的对应b'10000000000'的目标权限位。
哪怕是全权限的用户,只要逻辑判断的位不符合预期,这个条件就会触发错误。
2. 修正触发器代码
你需要把位运算的部分用括号括起来,确保先执行位与操作,再判断结果是否大于0:
SELECT permissions INTO @deleting_permission FROM users WHERE id = new.deleter_id; IF old.deleted <> new.deleted THEN -- 用括号明确位运算优先执行,再判断结果是否大于0 IF (IFNULL(((@deleting_permission & b'10000000000') > 0), 0) < 1) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = "You cannot delete post"; END IF; END IF;
3. 额外需要检查的细节
- 位掩码的位数是否匹配:你的
permissions是bit(15),b'10000000000'是11位二进制数,对应十进制的1024(2^10)。请确认这个掩码确实对应你想要控制的删除权限位,避免位位置搞反(比如把从左数的位当成了从右数的位)。 - 全权限赋值的验证:你用
UPDATE users SET permissions = -1 WHERE id = ?设置全权限是正确的——bit(15)类型存储-1时会转成15个1的补码(全权限)。可以用以下语句验证实际存储的二进制值:SELECT id, BIN(permissions) FROM users WHERE id = 2; new.deleter_id是否正确赋值:确保执行更新操作时,new.deleter_id确实被设置为目标用户的ID(比如2),如果这个字段为NULL,@deleting_permission会是NULL,IFNULL后返回0,也会触发错误。
内容的提问来源于stack exchange,提问作者Martin AJ
相关产品推荐
相关产品推荐

