MySQL更新表时带主键关联条件仍报Error Code:1175问题求助
MySQL 1175安全更新错误原因与解决方案
你的SQL语句业务逻辑没有错误,触发1175错误是MySQL安全更新模式(sql_safe_updates=1)的检查规则导致的。
错误触发原因
MySQL安全更新模式的判定逻辑非常直接,执行UPDATE/DELETE操作时必须满足以下两个条件之一才会放行:
- 语句最外层的WHERE子句中使用了带索引的列作为过滤条件
- 语句末尾带有LIMIT限制操作行数
该规则不会深入解析子查询内的关联逻辑,你当前的UPDATE语句外层没有显式写WHERE子句,属于全表更新操作,哪怕子查询内用到了主键transactionNo做关联,依然会被判定为不符合安全更新要求。
解决方法
方法1:修改SQL适配安全更新规则(无需关闭安全模式,更推荐)
有两种改法可选:
改法1:添加合法的WHERE条件
因为transactionNo是Payment表的主键,天然非空,你只需要在外层添加一个用到该索引列的恒真条件即可通过检查:
UPDATE Payment py SET total = (SELECT SUM(price) FROM Package pk WHERE py.transactionNo = pk.transactionNo) WHERE transactionNo IS NOT NULL;
改法2:改用多表关联更新写法(执行效率更高)
关联更新的写法可以避免子查询逐行计算的性能损耗,也能通过安全更新检查:
UPDATE Payment py LEFT JOIN ( SELECT transactionNo, SUM(price) AS sum_price FROM Package GROUP BY transactionNo ) pk ON py.transactionNo = pk.transactionNo SET py.total = COALESCE(pk.sum_price, 0);
COALESCE函数用于处理Payment中存在、但Package中无对应交易号的记录,将这类记录的total设为0,你可以根据业务需求调整默认值
方法2:临时关闭当前会话的安全更新模式
如果确认要执行全表更新,不需要修改编辑器全局设置,只需要在执行UPDATE语句前,执行一次会话级别的参数修改即可:
-- 临时关闭当前会话的安全更新 SET sql_safe_updates = 0; -- 执行你的UPDATE语句 UPDATE Payment py SET total = (SELECT SUM(price) FROM Package pk WHERE py.transactionNo = pk.transactionNo); -- 执行完成后重新开启安全更新,避免后续误操作 SET sql_safe_updates = 1;
内容的提问来源于stack exchange,提问作者JJBeaudry
相关产品推荐
相关产品推荐

