Oracle SQL跨表更新字段报错ORA-01427:子查询返回多行
解决ORA-01427: 单行子查询返回多行的问题
首先注意到你SQL里的字段名拼写错误:REGITRATION_NUMBER应该是REGISTRATION_NUMBER,先修正这个,避免因为拼写问题导致的额外错误。
错误原因很明确:你的EMPLOYEES表中,某个REGISTRATION_NUMBER值在TEMP表中对应了多条记录,而UPDATE语句中SET后面的子查询要求必须返回恰好一行,Oracle无法确定用哪一行的数据来更新,所以抛出这个错误。
下面给两种解决思路:
思路1:先清理TEMP表,保证每个REGISTRATION_NUMBER唯一
如果业务上TEMP表中每个REGISTRATION_NUMBER只应该对应一条记录,那先去重:
- 如果你有时间字段(比如记录创建时间
CREATE_DATE),保留最新的一条:
DELETE FROM TEMP t1 WHERE EXISTS ( SELECT 1 FROM TEMP t2 WHERE t2.REGISTRATION_NUMBER = t1.REGISTRATION_NUMBER AND t2.CREATE_DATE > t1.CREATE_DATE );
- 如果没有时间字段,直接保留每个
REGISTRATION_NUMBER的任意一条(用ROWID筛选):
DELETE FROM TEMP WHERE ROWID NOT IN ( SELECT MIN(ROWID) FROM TEMP GROUP BY REGISTRATION_NUMBER );
清理完TEMP表后,再执行你原来的UPDATE语句(记得修正拼写错误)即可。
思路2:在UPDATE子查询中强制返回单行
如果TEMP表的重复数据是合理的,你需要指定用哪一行来更新(比如取最大值、最小值,或者第一条):
- 用聚合函数(比如MAX,适合数值/字符串类型字段):
UPDATE employees e SET (e.SOCIAL_SECURITY_NUMBER, e.IBAN, e.ID_CARD) = ( SELECT MAX(t.AMKA), MAX(t.IBAN), MAX(t.ADT) FROM TEMP t WHERE t.REGISTRATION_NUMBER = e.REGISTRATION_NUMBER ) WHERE EXISTS ( SELECT 1 FROM TEMP t WHERE t.REGISTRATION_NUMBER = e.REGISTRATION_NUMBER );
- 用ROW_NUMBER()指定取某一行(比如按某个字段排序后的第一条):
UPDATE employees e SET (e.SOCIAL_SECURITY_NUMBER, e.IBAN, e.ID_CARD) = ( SELECT t.AMKA, t.IBAN, t.ADT FROM ( SELECT t.AMKA, t.IBAN, t.ADT, ROW_NUMBER() OVER (PARTITION BY t.REGISTRATION_NUMBER ORDER BY t.AMKA) rn -- 这里ORDER BY可以换成你需要的排序字段,比如CREATE_DATE FROM TEMP t WHERE t.REGISTRATION_NUMBER = e.REGISTRATION_NUMBER ) t WHERE rn = 1 ) WHERE EXISTS ( SELECT 1 FROM TEMP t WHERE t.REGISTRATION_NUMBER = e.REGISTRATION_NUMBER );
内容的提问来源于stack exchange,提问作者user13768246
相关产品推荐
相关产品推荐

