使用SET赋值子查询结果时触发「Subquery returns more than 1 row」错误求助
这个问题我之前也碰到过,本质原因是你用SET给单个变量赋值时,子查询返回了多个结果——而MySQL的普通用户变量只能存储单个值,自然就触发了"Subquery returns more than 1 row"的报错。给你几个实用的解决思路:
方案1:跳过变量,直接执行删除(最简洁高效)
既然你的最终目的是删除这些孤立记录,完全可以跳过赋值变量这一步,直接把查询逻辑整合到DELETE语句里:
DELETE FROM text_fields WHERE study_id NOT IN (SELECT id FROM studies);
这样既避免了变量的问题,又减少了中间步骤,执行效率也更高。
方案2:用GROUP_CONCAT把多值拼成字符串变量
如果一定要用变量来存储这些ID,可以用GROUP_CONCAT将多个ID拼接成逗号分隔的字符串,之后用FIND_IN_SET来匹配:
-- 先把所有符合条件的ID拼成字符串 SET @text_field_ids := ( SELECT GROUP_CONCAT(tf.id) FROM text_fields as tf WHERE tf.study_id NOT IN (select id from studies) ); -- 用FIND_IN_SET匹配字符串里的ID DELETE FROM text_fields WHERE FIND_IN_SET(id, @text_field_ids);
⚠️ 注意:GROUP_CONCAT有默认长度限制(默认1024字符),如果你的ID数量很多,可能会被截断。可以先执行SET SESSION group_concat_max_len = 1000000;来临时调整会话级别的长度限制。
方案3:用临时表存储多值(适合大数据量场景)
如果你的孤立记录数量非常多,用字符串变量可能有长度风险,建议用临时表来存储这些ID:
-- 创建临时表存储需要删除的ID CREATE TEMPORARY TABLE temp_text_field_ids SELECT id FROM text_fields WHERE study_id NOT IN (SELECT id FROM studies); -- 通过临时表执行删除 DELETE FROM text_fields WHERE id IN (SELECT id FROM temp_text_field_ids); -- 用完可以删除临时表(可选,会话结束会自动销毁) DROP TEMPORARY TABLE temp_text_field_ids;
临时表的优势是没有长度限制,处理大量数据时更稳定。
内容的提问来源于stack exchange,提问作者Kris
相关产品推荐
相关产品推荐

