使用refcursor调用Redshift存储过程报错问题咨询
问题原因
- 第一个报错
Invalid operation for this statement object是因为单个PreparedStatement对象同一时间只能绑定一个SQL操作,已经执行过存储过程调用的语句对象不能直接复用执行fetch查询。 - 第二个报错
cursor "rs" does not exist是因为Redshift的refcursor是事务级资源,JDBC连接默认开启自动提交,执行完存储过程调用后事务自动提交,游标会被立即销毁,后续新建的语句对象自然找不到对应游标。
解决方案
核心操作
调用存储过程前先关闭连接的自动提交,保证游标生命周期内事务不被自动提交,使用同一连接下的新语句对象执行fetch操作即可。
正确代码示例
// 第一步:关闭连接自动提交 connection.setAutoCommit(false); // 第二步:执行存储过程调用 PreparedStatement callStmt = connection.prepareStatement("call myproc( null, null, 3, 4, 'rs' )"); callStmt.execute(); // 第三步:用同一连接创建新的语句对象执行fetch PreparedStatement fetchStmt = connection.prepareStatement("fetch all from rs"); ResultSet resultSet = fetchStmt.executeQuery(); // 第四步:处理结果集(此处补充你自己的业务逻辑) while (resultSet.next()) { // 自行处理每行返回数据 } // 第五步:资源清理+事务提交 resultSet.close(); fetchStmt.close(); callStmt.close(); connection.commit(); // 若需要恢复JDBC默认自动提交配置,可新增以下代码 // connection.setAutoCommit(true);
依赖说明
你当前使用的redshift-jdbc42-no-awssdk 1.2.37.1061版本完全支持refcursor相关操作,无需调整依赖版本。
注意事项
- 如果操作过程中抛出异常,需要调用
connection.rollback()回滚事务,避免事务长期挂起占用连接资源。 - 游标仅在当前未提交的事务内有效,事务提交或回滚后都会被销毁,无法再访问。
内容的提问来源于stack exchange,提问作者ankursingh1000
相关产品推荐
相关产品推荐

