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

调用返回BOOLEAN的PL/SQL函数报SQL错误[17004]求助

解决Spring JDBC调用Oracle PL/SQL BOOLEAN函数的17004错误

你遇到的Type de colonne non valide: 1111(无效列类型1111)错误,核心原因是JDBC规范本身不支持Oracle PL/SQL的BOOLEAN类型,Oracle JDBC驱动无法直接映射这个类型到Java的Boolean,再加上你的Java代码获取返回值的方式完全错误,导致了这个异常。

问题拆解

  • PL/SQL BOOLEAN的JDBC兼容性问题:JDBC没有将BOOLEAN定义为标准SQL类型,Oracle的PL/SQL BOOLEAN属于数据库内部专属类型,JDBC驱动无法直接识别处理。
  • Java代码的逻辑错误:你尝试通过cs.getResultSet().toString()获取返回值,但这个函数返回的是单个BOOLEAN值,不是结果集,这种获取方式完全不符合函数调用的逻辑。

解决方案

这里提供两种可靠的解决方式,你可以根据实际场景选择:

方案一:修改PL/SQL函数,返回JDBC兼容类型(推荐)

把PL/SQL函数的返回类型从BOOLEAN改为NUMBER,用1代表TRUE,0代表FALSE,这样JDBC可以直接处理该类型:

FUNCTION F_IsDemandeDeLitFromHosp(i_NoMvtHosp IN MVTHOSP.NOMVTHOSP%TYPE )RETURN NUMBER IS 
v_Found NUMBER := 0; 
BEGIN 
  BEGIN 
    SELECT COUNT(1) INTO v_Found 
    FROM ICSF.T_DEMANDE_LIT D, MVTUS U, MVTHOSP H 
    WHERE H.NOMVTHOSP = i_NoMvtHosp 
      AND H.NOMVTHOSP = U.NOMVTHOSP 
      AND U.NOMVTUS = D.NOMVTUS 
      AND U.RANG <> '0000000000' 
      AND H.RANG = '0000100000' 
      AND NVL (D.ETAT, ' ') <> 'X' 
      AND NVL (U.ETAT, ' ') <> 'X' 
      AND NVL (H.ETAT, ' ') <> 'X' 
      AND ROWNUM = 1; 
  EXCEPTION WHEN OTHERS THEN RETURN 0; 
  END; 
  RETURN CASE WHEN v_Found > 0 THEN 1 ELSE 0 END; 
END F_IsDemandeDeLitFromHosp;

同步修改Java代码,获取返回的数值并转为Boolean:

@Override 
public DemandeDeLitFromHospit isDemandeDelitFromHosp(String noMvtHosp) { 
  final ProcedureRequest request = new ProcedureRequest(
      PK.GET_IS_DEMANDE_DE_LIT_FROM_HOSP.getPackageName(), 
      PK.GET_IS_DEMANDE_DE_LIT_FROM_HOSP.getMethodeName()
  ); 
  request.addInParam("i_NoMvtHosp", noMvtHosp); 
  // 注册输出参数为JDBC支持的NUMERIC类型
  request.addOutParam("return", Types.NUMERIC);

  DemandeDeLitFromHospit demande = new DemandeDeLitFromHospit(); 
  Integer result = (Integer) callFunction(request, new CallableStatementCallback<Integer>() { 
    public Integer doInCallableStatement(CallableStatement cs) throws SQLException { 
      cs.execute(); 
      // 函数返回值对应第一个输出参数
      return cs.getInt(1); 
    } 
  }); 
  demande.setIsDemandeDeLitFromHosp(result != null && result == 1); 
  return demande; 
}

方案二:不修改PL/SQL,使用Oracle特定API处理

如果你无法修改PL/SQL函数,可以使用Oracle官方JDBC驱动提供的OracleCallableStatement来处理BOOLEAN类型:

@Override 
public DemandeDeLitFromHospit isDemandeDelitFromHosp(String noMvtHosp) { 
  final ProcedureRequest request = new ProcedureRequest(
      PK.GET_IS_DEMANDE_DE_LIT_FROM_HOSP.getPackageName(), 
      PK.GET_IS_DEMANDE_DE_LIT_FROM_HOSP.getMethodeName()
  ); 
  request.addInParam("i_NoMvtHosp", noMvtHosp); 

  DemandeDeLitFromHospit demande = new DemandeDeLitFromHospit(); 
  Boolean result = callFunction(request, new CallableStatementCallback<Boolean>() { 
    public Boolean doInCallableStatement(CallableStatement cs) throws SQLException { 
      // 转换为Oracle专属的CallableStatement
      OracleCallableStatement ocs = (OracleCallableStatement) cs;
      // 注册输出参数为Oracle的BOOLEAN类型
      ocs.registerOutParameter(1, OracleTypes.BOOLEAN);
      ocs.execute(); 
      // 获取布尔返回值
      return ocs.getBoolean(1); 
    } 
  }); 
  demande.setIsDemandeDeLitFromHosp(result != null && result); 
  return demande; 
}

关键注意事项

  • PL/SQL函数的返回值是通过输出参数传递的,不要尝试从getResultSet()获取,这是针对查询语句的方法。
  • JDBC不支持PL/SQL BOOLEAN是核心矛盾,要么修改PL/SQL兼容JDBC,要么使用Oracle专属API绕开限制。

内容的提问来源于stack exchange,提问作者guicontat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:52:47