使用其他表计算值更新payout表时遭遇1175错误的技术咨询
问题背景
现有两张表:
orders表
payout_id subtotal p_p ------------------------ 1 10 2 1 11 3 2 15 NULL 3 20 5
更新前的payout表(payout_id为主键)
payout_id income ------------------ 1 2 3
需要将payout表的income字段更新为对应payout_id在orders表中subtotal + IFNULL(p_p, 0)的总和,期望结果:
payout_id income ----------------- 1 26 2 15 3 25
编写的更新语句逻辑正确,但执行时触发错误:
Error Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column. To disable safe mode, toggle the option in Preferences -> SQL Editor and reconnect.
当WHERE子句改为WHERE payout.payout_id = '1'时可成功更新单行,但批量更新时报错。
错误原因
MySQL的安全更新模式(SQL_SAFE_UPDATES)要求UPDATE/DELETE语句的WHERE子句必须包含直接引用更新表中KEY列的过滤条件。你原语句中的WHERE payout.payout_id = temp.payout_id虽然用到了主键,但这是基于关联子查询的等值判断,安全模式的检测逻辑无法识别这是对主键的直接约束,因此触发报错。
解决方案
方案1:修改WHERE子句,添加直接针对主键的条件
既然payout_id是主键(非空且唯一),可以添加一个简单的基于主键的条件,让安全模式认可:
UPDATE payout INNER JOIN ( SELECT payout_id, SUM(subtotal + IFNULL(p_p, 0)) AS payout_total FROM orders GROUP BY payout_id ) temp ON payout.payout_id = temp.payout_id SET payout.income = temp.payout_total WHERE payout.payout_id IS NOT NULL; -- 主键不可能为NULL,仅用于满足安全模式要求
或者用IN子句明确指定主键范围:
UPDATE payout INNER JOIN ( SELECT payout_id, SUM(subtotal + IFNULL(p_p, 0)) AS payout_total FROM orders GROUP BY payout_id ) temp ON payout.payout_id = temp.payout_id SET payout.income = temp.payout_total WHERE payout.payout_id IN (SELECT payout_id FROM orders);
方案2:临时关闭安全更新模式(推荐操作后重新开启)
如果不需要保留安全模式的限制,可以临时关闭后执行更新:
-- 关闭安全更新模式 SET SQL_SAFE_UPDATES = 0; -- 执行更新(INNER JOIN已过滤出需要更新的行,可省略冗余的WHERE子句) UPDATE payout INNER JOIN ( SELECT payout_id, SUM(subtotal + IFNULL(p_p, 0)) AS payout_total FROM orders GROUP BY payout_id ) temp ON payout.payout_id = temp.payout_id SET payout.income = temp.payout_total; -- 重新开启安全更新模式(可选,推荐保持安全模式以避免误操作) SET SQL_SAFE_UPDATES = 1;
说明
你的原更新逻辑是正确的,问题仅出在安全模式的约束上。两种方案都可以实现批量更新,选择哪种取决于你是否需要保持安全模式的开启状态。
内容的提问来源于stack exchange,提问作者Kat Pritchett

