多OR子查询返回多行错误:Oracle正常但Hibernate调用异常
「single-row subquery returns more than one row」错误排查与环境差异解释
错误定位
错误根源在于SQL中以下子查询逻辑:
( SELECT CHP.CRI_KEY_PARENT FROM S4C_CRITERIA_HERITANCE CHP WHERE CHP.CRI_KEY_CHILD = CRI.CRI_KEY ) IN ( SELECT CBB.CRI_KEY FROM S4C_CRITERIA CBB WHERE CBB.SPRM_KEY = P.SPRM_PARENT_KEY )
Oracle要求IN操作符左侧的子查询必须返回单行单列结果。如果S4C_CRITERIA_HERITANCE表中存在某个CRI_KEY_CHILD对应多条CRI_KEY_PARENT记录,左侧子查询会返回多行,直接触发「single-row subquery returns more than one row」错误。
环境差异原因
- Oracle SQL Developer正常执行:你在SQL Developer中使用的测试数据里,所有匹配的
CRI_KEY_CHILD在S4C_CRITERIA_HERITANCE中仅对应一条父记录,子查询始终返回单行,因此不会报错。 - Postman调用报错:通过Hibernate发起请求时,业务数据中存在
CRI_KEY_CHILD对应多条CRI_KEY_PARENT的场景,此时左侧子查询返回多行,触发Oracle的语法约束错误。此外,Hibernate可能因参数绑定、会话上下文等因素,查询范围与SQL Developer中不一致,命中了包含多父记录的数据集。
修复方案
将原有的子查询IN逻辑替换为EXISTS关联查询,避免单行子查询的限制:
WITH SPRM_TABLE AS ( SELECT DISTINCT P.SPRM_KEY, P.SPRM_PARENT_KEY AS PARENTS, P.CPRM_KEY, P.SPRM_PARENT_KEY FROM S4C_SUB_PERIMETER P INNER JOIN S4C_CRITERIA CRI ON CRI.SPRM_KEY = P.SPRM_KEY WHERE ( CRI.CRI_TYPE = 'OFFER' AND CRI.CRI_VALUE = 'BUSINESS_ETHERNET' ) OR ( ( P.SPRM_PARENT_KEY IS NULL OR ( CRI.CRI_TYPE IN ( 'SATIN_ACCOUNT', 'SATIN_SUBACCOUNT', 'IDENT_RCE', 'ICO1' ) AND EXISTS ( SELECT 1 FROM S4C_CRITERIA_HERITANCE CHP JOIN S4C_CRITERIA CBB ON CHP.CRI_KEY_PARENT = CBB.CRI_KEY WHERE CHP.CRI_KEY_CHILD = CRI.CRI_KEY AND CBB.SPRM_KEY = P.SPRM_PARENT_KEY ) ) ) AND ( CRI.CRI_TYPE = 'IDENT' AND CRI.CRI_VALUE = '00010525' ) ) ) SELECT DISTINCT CPRM.CPRM_KEY AS PRM_ID, 'CLIENT' AS PRM_TYPE FROM CPRM_TABLE CPRM UNION ALL SELECT DISTINCT PRM.SPRM_KEY AS PRM_ID, 'SUB' AS PRM_TYPE FROM SPRM_TABLE PRM START WITH PRM.SPRM_PARENT_KEY IS NULL AND PRM.CPRM_KEY IN ( SELECT CLI_PRM.CPRM_KEY FROM CPRM_TABLE CLI_PRM ) CONNECT BY PRIOR PRM.SPRM_KEY = PRM.SPRM_PARENT_KEY
内容的提问来源于stack exchange,提问作者AEL
相关产品推荐
相关产品推荐

