You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 11:55:37