只设置一些参数时,如何在 JDBC 中调用存储过程

Posted

技术标签:

【中文标题】只设置一些参数时,如何在 JDBC 中调用存储过程【英文标题】:How in JDBC can you call a stored procedure when only setting some parameters 【发布时间】:2012-08-06 12:10:45 【问题描述】:

如果您只想设置一些参数,那么使用 JDBC 调用存储过程的最佳方法是什么?

如果我只是使用 SQL,我可以在 SQL 中按名称设置参数以调用存储过程。例如。如果我有一个包含九个参数的存储过程,并且我想设置参数 1,2 和 9,其余的保留为默认值,我可以运行以下 SQL:

exec my_stored_procedure
    @parameter_1       = "ONE",
    @parameter_2       = "TWO",
    @parameter_9       = "NINE"

使用 JDBC(特别是 jConnect 6.0),似乎在使用 CallableStatement 时,您必须通过它们的整数索引而不是它们的名称来设置参数。如果我尝试为上述存储过程创建一个 CallableStatement,带有 9 个参数,并且只设置参数 1,2 和 9,如下所示:

myStoredProcedureCall = 
  sybConn.prepareCall("call my_stored_procedure (?, ?, ?, ?, ?, ? , ?, ?, ?)");
myStoredProcedureCall.setString(1, "ONE");
myStoredProcedureCall.setString(2, "TWO");
myStoredProcedureCall.setString(9, "NINE");
ResultSet paramResults = myStoredProcedureCall.executeQuery();

然后我得到这个 SQLException 抛出:

*** SQLException caught ***
SQLState: JZ0SA
Message:  JZ0SA: Prepared Statement: Input parameter not set, index: 2.
Vendor:   0

对于我正在尝试做的事情的一些背景知识,我需要创建一个流程,从 IBM MQ 流中接收有关产品的信息,然后在第三个应用程序中创建一个产品。第 3 方应用程序使用 Sybase 来存储它的数据,并创建一个产品,我需要调用一个具有大约 130 个参数的存储过程。对于我需要创建的产品类型,这些参数只需要设置大约15个,其余的将保留默认值。

我考虑过的选项是:

创建一个只设置我需要的值的自定义存储过程,然后调用第 3 方产品存储过程。 为 Java 中的所有参数设置默认值。

肯定有更简单的方法来做到这一点?

【问题讨论】:

【参考方案1】:

JDBC 不支持此功能。您必须创建一个 SQL 字符串并执行它:

String sql = "exec my_stored_procedure\n@parameter_1 = ?,\n@parameter_2 = ?,\n@parameter_9 = ?";

PreparedStatement stmt = ...
stmt.setString( 1, "ONE" );
stmt.setString( 2, "TWO" );
stmt.setString( 3, "NINE" );
stmt.execute();

记住:除了? 等一些特殊字符外,JDBC 不会尝试理解您发送到数据库的SQL。我曾经写过一个 JDBC“数据库”,它接受 javascript sn-ps 作为“SQL”:我简单地实现了 DataSourceConnectionResultSet,我可以使用 JDBC 接口查询我的应用程序的内存模型,但使用 JavaScript 作为查询语言。

【讨论】:

对于其他需要上述示例的人,String sql 中的 '\n' 可以只替换为一个空格。 Sybase 不需要将参数列在单独的行上,它们只需用逗号分隔即可。 @alaniane 正确。我从一些代码中复制了这个例子,我也记录了这些语句。换行符只是为了帮助人们理解 SQL。【参考方案2】:

您可以尝试在字符串中硬编码 null 或空白

"call my_stored_procedure (?, ?, null, null, null, null , null, null, ?)"

【讨论】:

如果我指定 null,则参数不会在 Sybase 存储过程中设置为默认值。【参考方案3】:
myStoredProcedureCall.setString(9, "NINE");

in above code index no 9 but it will be 3 because your parameter sequence start from 1 ;
Alhrough  you can another sql exception.

I think you should use 

myStoredProcedureCall = 
  sybConn.prepareCall("call my_stored_procedure (?, ?, null, null, null, null , null, null, ?)");
myStoredProcedureCall.setString(1, "ONE");
myStoredProcedureCall.setString(2, "TWO");
myStoredProcedureCall.setString(3, "NINE");
ResultSet paramResults = myStoredProcedureCall.executeQuery();

【讨论】:

【参考方案4】:

//abobjects.com 下面对我有用 def getIDGEN(sTableName): proc = db.prepareCall(" ? = call DB.dbo.usp_IDGEN_string_v6(?, ?) ");

proc.registerOutParameter(3, types.INTEGER)
proc.setString(2, sTableName)
proc.setInt(3, 0)   
proc.execute()
li_RI_ID = proc.getInt(3)
print str(li_RI_ID) + " obtained from usp_IDGEN_string_v6"
return li_RI_ID

我的存储过程是

create proc usp_IDGEN_string_v6 (@tablename  varchar(32) , @ID  numeric )
as
declare @seq     numeric
declare @nextID  numeric
select @nextID=IDGEN_ID from DB_IDGEN where IDGEN_TableName = @tablename
select @seq=@nextID + 1 from DB_IDGEN where IDGEN_Table
 Name = @tablename
update DB_IDGEN set IDGEN_ID = @seq where IDGEN_TableName = @tablename
select @ID  = @seq
return @ID

【讨论】:

以上是关于只设置一些参数时,如何在 JDBC 中调用存储过程的主要内容,如果未能解决你的问题,请参考以下文章

SQL存储过程如何调用存储过程?

在某些参数类型是用户定义的情况下,如何使用 JDBC/Spring 调用 Oracle 存储过程?

如何使用 JDBC 调用带有命名参数的 Sybase 存储过程

JDBC 调用函数或存储过程

Hana 参数化存储过程问题简单 jdbc 模板

如何获取作为数组工作的存储过程输出参数?