1

我正在使用官方 Sybase JDBC 驱动程序连接到数据库并通过创建 CallableStatement、将参数绑定到它并在其上调用 .execute() 来调用存储过程。

但是,我发现即使存储过程失败,也没有抛出异常。我可以通过使用 Wireshark 嗅探到数据库的流量并观察返回的错误消息来验证故障是否传播回给我。

最后我发现使用 .executeUpdate() 而不是 .execute()确实给了我例外,但是我还有两个问题:

  1. 为什么 .execute() 和 .executeUpdate() 表现不同?从界面的 SUN 文档看来,他们应该(几乎)做同样的事情......
  2. 调用存储过程时将 .execute() 替换为 .executeUpdate() 是否总是合适的?存储过程必须符合某些特定要求才能使用 .executeUpdate() 调用吗?(例如,它必须有一个更新/删除/插入语句作为最后一步吗?)

更新:我尝试过 jTDS,它的行为正确(如:它在两种情况下都抛出 SQLException - 使用 .execute() 和使用 .executeUpdate())。但是,由于我无法控制的限制,切换驱动程序是不可能的。

另外:我对这个存储过程返回的结果不感兴趣,它是一个插入/更新类型的过程。我只会被插入以查看(并且能够捕获/记录)它是否失败。我尝试过的另一件事是在 .execute() 之后从连接中获取警告,但它也不包含任何内容。

4

3 回答 3

5

因为那些 Sybase 人都疯了,所以才会吃 Exceptions!没有理由避免对准备好的/可调用的语句使用 executeUpdate()。如果这是您必须使用它来使其正常工作,那么请继续这样做。但是您应该向 Sybase 提交错误报告 - 驱动程序没有理由这样做。

于 2009-04-20T20:34:57.877 回答
1

不确定,sybase的人是否“疯了”。也许。

另一方面,当您不主动检查可调用语句的返回代码时,不同步检索结果可能在性能方面有意义。我还没有完全测试它,但是有一个简单的解决方法可以解决您的问题(ASE 15.5,jconn 7):

当您从存储过程中获取输出参数时(至少在调用存储过程时),将触发异常:

    // one may force the error check by retrieving the return code!
    cs = conn.prepareCall("{ ? = call sp_nested_error @nNestLevels = 1 }");
    cs.registerOutParameter(1, Types.INTEGER);
    cs.execute();
    try {
        cs.getInt(1);
        fail();
    } catch(SQLException e) {
        assertTrue(e.getMessage().indexOf("some error") > -1);
    }

另一个令人好奇的是,这种行为仅在嵌套存储过程调用中触发错误时才会出现,而当最顶层的过程引发错误时,解决方法不是必需的。

于 2012-08-06T11:46:38.933 回答
0

对 Sybase 一无所知,但是

executeUpdate 返回比执行更多的信息:插入/更新/删除的行数

-> 根据 javadoc,它可用于 UPDATE INSERT DELETE 和 DML 操作。

executeQuery 返回一个 ResultSet,这是用于 SELECT 语句的。

于 2009-04-16T07:17:26.817 回答