MySQL更新表时子查询报错:Subquery returns more than 1 row
解决UPDATE语句中"Subquery returns more than 1 row"的问题
兄弟,你遇到的这个错误本质是子查询返回了多行结果,而UPDATE的SET子句要求赋值的子查询必须为每一行待更新的记录返回唯一值。咱们一步步来排查和解决:
错误根源分析
你的原语句里的WHERE条件大概率出了逻辑优先级问题:AND的优先级比OR高,所以原条件会被数据库解析成:
(o.id_orden = h.id_orden AND h.estado_origen = 'OrdenWorkflow/cancelada' AND h.estado_fin = '') OR h.estado_fin = ...
这就导致h.estado_fin = ...的条件会匹配所有符合的记录,不管id_orden是否和主表一致,最终子查询返回了多个不同id_orden的最大值,触发报错。
另外,即使条件逻辑对了,如果没有明确按id_orden分组,也可能因为某些意外情况(比如同一id_orden有多个符合条件的记录,但MAX本来应该返回唯一值,但如果条件写错还是会出问题)。
两种解决方案
方案1:修正子查询的逻辑优先级+明确分组
先给OR的条件加上括号,确保它是和h.estado_origen的条件并列的,同时通过GROUP BY保证每个id_orden只返回一个最大值:
UPDATE orden o SET fecha_cancelacion = ( SELECT MAX(CAST(fecha AS DATETIME)) FROM historico_estados_orden h WHERE o.id_orden = h.id_orden AND h.estado_origen = 'OrdenWorkflow/cancelada' AND (h.estado_fin = '' OR h.estado_fin = '你没写完的那个值') -- 这里补全你的条件,记得加括号 GROUP BY h.id_orden ) -- 可选:如果只想更新有匹配记录的行,加上这个WHERE子句,避免把无匹配的行设为NULL WHERE EXISTS ( SELECT 1 FROM historico_estados_orden h WHERE o.id_orden = h.id_orden AND h.estado_origen = 'OrdenWorkflow/cancelada' AND (h.estado_fin = '' OR h.estado_fin = '你没写完的那个值') );
方案2:用JOIN方式更新(更直观,避免子查询陷阱)
很多时候用JOIN来做批量更新比子查询更稳妥,也更容易排查问题:
UPDATE orden o JOIN ( SELECT id_orden, MAX(CAST(fecha AS DATETIME)) AS latest_cancel_date FROM historico_estados_orden WHERE estado_origen = 'OrdenWorkflow/cancelada' AND (estado_fin = '' OR estado_fin = '你没写完的那个值') GROUP BY id_orden ) h ON o.id_orden = h.id_orden SET o.fecha_cancelacion = h.latest_cancel_date;
验证建议
在执行UPDATE之前,先单独运行子查询部分,看看返回的结果是不是每个id_orden对应唯一的最大值:
SELECT id_orden, MAX(CAST(fecha AS DATETIME)) AS latest_cancel_date FROM historico_estados_orden WHERE estado_origen = 'OrdenWorkflow/cancelada' AND (estado_fin = '' OR estado_fin = '你没写完的那个值') GROUP BY id_orden;
如果这个查询返回的id_orden没有重复,那说明逻辑没问题,再执行UPDATE就不会报错了。
内容的提问来源于stack exchange,提问作者In0cybe
相关产品推荐
相关产品推荐

