我很担心Sybase JDBC驱动程序如何处理混合IN
和OUT
参数的存储过程。看看这个简单的存储过程:
CREATE OR REPLACE PROCEDURE p (IN i1 INT, OUT o1 INT, IN i2 INT, OUT o2 INT)
BEGIN
set o1 = i1;
set o2 = i2;
END
以下是我用JDBC调用的方法:
CallableStatement c = connection.prepareCall("{ call dba.p(?, ?, ?, ?) }");
c.setInt(1, 1);
c.setInt(3, 2);
c.registerOutParameter(2, Types.INTEGER);
c.registerOutParameter(4, Types.INTEGER);
c.execute();
System.out.println(c.getObject(2));
System.out.println(c.getObject(4));
但这会导致
1
null
发生了什么事?这是JDBC驱动程序中的一个非常邪恶的错误还是我完全错过了什么?通过反复试验,我发现这是一种工作方式:
c.setInt(1, 1);
c.setInt(2, 2);
c.registerOutParameter(3, Types.INTEGER);
c.registerOutParameter(4, Types.INTEGER);
c.execute();
System.out.println(c.getObject(3));
System.out.println(c.getObject(4));
现在结果是
1
2
JDBC驱动程序是否秘密重新排序IN
和OUT
参数??
我正在使用SQL Anywhere 12和jconn3.jar
答案 0 :(得分:7)
看起来像是驱动程序中的错误。
我怀疑有缺陷的驱动程序希望参数在顺序中传递/注册(即1,2,3,4)。当你执行registerOut(2)时,语句显然忘记了你做了set(3): - )
或者,可能是所有OUT应该在所有IN之后完成。然后,这是驱动程序中的一个错误。
<强>更新强>
等等,你没有改变第二个变种的程序?该结果不会产生任何感。除非,如你所说,司机重新排序。至少可以说,不寻常。
更新2
我已经反编译了驱动程序。它做了一些非常有趣的游戏围绕参数,并且所有这些joggling我觉得他们有一个公平的潜在的bug,但到目前为止,我没有明白地看到它。
我注意到的唯一有趣的事情是,显然如果位置n的参数没有输出,驱动程序将向前扫描参数,直到它找到值;如果找不到值,则转到下一行:
s.registerOutParameter(5,Types.INT);
...
// no out value at position 4, it will go to 5 and get the value
rs.getInteger(4);
更新3
看到例1中所有4个参数的输出可能很有意思,即:
CallableStatement c = connection.prepareCall("{ call dba.p(?, ?, ?, ?) }");
c.setInt(1, 1);
c.setInt(3, 2);
c.registerOutParameter(2, Types.INTEGER);
c.registerOutParameter(4, Types.INTEGER);
c.execute();
System.out.println(c.getObject(1));
System.out.println(c.getObject(2));
System.out.println(c.getObject(3));
System.out.println(c.getObject(4));
答案 1 :(得分:4)
我尝试使用Oracle 9.2并且它按预期工作。我认为这个问题与您的JDBC驱动程序有关,而不是与JDBC本身有关。
public static void main(String[] args) throws Exception {
Connection connection = getConnection();
CallableStatement c = connection.prepareCall("{ call p(?, ?, ?, ?) }");
c.setInt(1, 1);
c.setInt(3, 2);
c.registerOutParameter(2, Types.INTEGER);
c.registerOutParameter(4, Types.INTEGER);
c.execute();
System.out.println(c.getObject(2));
System.out.println(c.getObject(4));
}
输出:
Connected to database
1
2
答案 2 :(得分:1)
Below sybase stored procedure works for me
public String IDGEN(String tableName, Connection con , LOG _log)
{
String strReturnValue = "-1";
try
{
CallableStatement cs = con.prepareCall("{call usp_NEWPK_string_v6(?,?)}");
cs.registerOutParameter(2,java.sql.Types.NUMERIC);
cs.setString(1,tableName);
cs.setInt(2,0);
cs.execute();
strReturnValue = cs.getLong(2) + "";
} catch (Exception ex) {
_log.logInstance(" ERROR: [IDGEN] " + ex.getMessage());
}
return strReturnValue;
}
// abobjects.com
create proc usp_NEWPK_string_v6 (@tablename varchar(32) , @ID numeric output
)
as
declare @newValue numeric
declare @oldValue numeric
select @oldValue=IDGEN_ID from DB_IDGEN where IDGEN_TableName = @tablename
select @newValue=@oldValue + 1 from DB
_IDGEN where IDGEN_TableName = @tablename
update DB_IDGEN set IDGEN_ID = @newValue where IDGEN_TableName = @tablename
select @ID = @oldValue
return