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

如何用Java读取PL/SQL存储过程返回的字符串输出?

HANA存储过程Java调用:读取输出参数而非ResultSet的问题

你现在遇到的问题很典型——用普通Statement的executeQuery()去调用带OUT参数的HANA存储过程,自然会报错,因为这个方法只适用于返回结果集的SQL语句(比如SELECT),而你的存储过程是通过OUT参数返回字符串,根本不会生成ResultSet。好消息是完全不用修改存储过程,只要调整Java的调用方式就可以解决。

先回顾下你的存储过程和出错的Java代码:

你的HANA存储过程代码

create PROCEDURE "PRATIK"."PRC_test3" (
    IN param1 INT, 
    param2 NVARCHAR(15), 
    OUT outParam1 VARCHAR (2000)
) 
LANGUAGE SQLSCRIPT 
SQL SECURITY INVOKER 
AS BEGIN 
    ----------- ### Exception Handler ### ------------------------ 
    DECLARE EXIT HANDLER FOR SQLEXCEPTION 
    BEGIN 
        outParam1 := 'SQL Exception occured. Error Code is: ' || ::SQL_ERROR_CODE || ' Error message is: ' || ::SQL_ERROR_MESSAGE; 
    END; 
    outparam1 := ' Param2: ' || :param2 || '| param1: ' || :param1; 
END;

出错的Java调用代码

if (connection != null) {
    try {
        String Stm = "CALL \"PRATIK\".\"PRC_test3_2\"("+param1+",'"+param2+"',"+outparams1+")";
        System.out.println("Connection to HANA successful!");
        java.sql.Statement stmt = connection.createStatement();
        java.sql.ResultSet resultSet = stmt.executeQuery(Stm);
        resultSet.next();
        String res1 = resultSet.getString(1);
        System.out.println("This is the result of the query -- "+res1);
        //System.out.println("METADATA -- "+resultSet.getMetaData());
    } catch (SQLException e) {
        System.err.println("Query failed!");
        System.err.println(e.getStackTrace());
        e.printStackTrace();
    }
}

报错信息

Query failed! [Ljava.lang.StackTraceElement;@6504e3b2 com.sap.db.jdbc.exceptions.JDBCDriverException: SAP DBTech JDBC: SQL statement does not generate a result set.
at com.sap.db.jdbc.exceptions.SQLExceptionSapDB._newInstance(SQLExceptionSapDB.java:197)
at com.sap.db.jdbc.exceptions.SQLExceptionSapDB.newInstance(SQLExceptionSapDB.java:26)
at com.sap.db.jdbc.StatementSapDB._executeQuery(StatementSapDB.java:1355)
at com.sap.db.jdbc.StatementSapDB.executeQuery(StatementSapDB.java:162)
at com.saphana.tibco.Procedure.main(Procedure.java:33)

解决方案:使用CallableStatement处理OUT参数

要读取存储过程的OUT参数,你需要用JDBC的CallableStatement,而不是普通的Statement。它专门用来处理存储过程的调用,支持注册IN/OUT参数。

修改后的Java代码如下:

if (connection != null) {
    try {
        // 使用?作为参数占位符,避免SQL注入,同时正确处理参数类型
        String callSql = "{ CALL \"PRATIK\".\"PRC_test3\"(?, ?, ?) }";
        java.sql.CallableStatement callStmt = connection.prepareCall(callSql);
        
        // 设置IN参数
        callStmt.setInt(1, param1); // 第一个参数是param1(INT类型)
        callStmt.setString(2, param2); // 第二个参数是param2(NVARCHAR类型)
        
        // 注册OUT参数:第三个参数是outParam1,类型是VARCHAR(2000),对应JDBC的Types.VARCHAR
        callStmt.registerOutParameter(3, java.sql.Types.VARCHAR);
        
        System.out.println("Connection to HANA successful!");
        // 执行存储过程,用execute()而不是executeQuery()
        callStmt.execute();
        
        // 获取OUT参数的值
        String res1 = callStmt.getString(3);
        System.out.println("This is the output parameter value -- " + res1);
        
        // 关闭资源
        callStmt.close();
    } catch (SQLException e) {
        System.err.println("Stored procedure call failed!");
        e.printStackTrace();
    }
}

关键修改点说明:

  1. 使用占位符?:避免直接拼接SQL导致的SQL注入风险,同时让JDBC正确处理参数类型转换。
  2. CallableStatement替代Statement:这是处理存储过程的标准方式,支持注册OUT参数。
  3. registerOutParameter:必须提前告诉JDBC OUT参数的类型,这里你的outParam1是VARCHAR类型,对应java.sql.Types.VARCHAR。
  4. 用execute()执行:因为存储过程不返回ResultSet,所以不能用executeQuery(),改用execute()方法。
  5. 通过getXXX()获取OUT参数:执行完成后,直接通过getString(3)获取第三个参数(也就是outParam1)的值,不需要处理ResultSet。

这样修改后,你不用改任何存储过程代码,就能正常读取到OUT参数返回的字符串了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:37:30