PreparedStatement 不适用于 Java 中的 Sybase IQ

Posted

技术标签:

【中文标题】PreparedStatement 不适用于 Java 中的 Sybase IQ【英文标题】:PreparedStatement Does Not Work For Sybase IQ In Java 【发布时间】:2019-05-28 16:02:01 【问题描述】:

我和我的团队遇到了一个问题。我们正在尝试从 Sybase IQ 数据库中检索一些数据,并使用where 子句过滤并获取特定数据。

SQL 已经过测试并且工作正常,但在使用 Prepared Statement 时会失败。

测试完成

    如果我们运行查询(带或不带 where 子句参数),它工作正常。 如果我们使用在 Prepared Statement 中硬编码的参数运行查询,它也可以正常工作。 如果我们以编程方式设置预处理语句的参数,它就不起作用。

以上测试确认 JDBC 连接工作正常。

使用 PreparedStatement、JdbcTemplate 或 NamedParameterJdbcTemplate 时会出现相同的错误,因此我怀疑 PreparedStatement 和 Sybase IQ 之间可能存在问题。

有人可以帮忙调查一下吗?我们已经找到了一种解决方法,但是知道为什么这不起作用会非常有用。

我在同一问题上发现了非常相似的主题 (How do I execute PreparedStatement(select object_id()) in sybase iq?),但没有人在那里提供可接受且正确的答案,因此我决定为此创建一个新问题。

使用的代码是:

Class.forName("com.sybase.jdbc4.jdbc.SybDriver");

PreparedStatement stmt = con.prepareStatement("select * from myView where off = ? and acc = ?");

stmt.setString(1, "260");
stmt.setString(2, "9050V");
ResultSet set = stmt.executeQuery();

错误信息是:

Exception in thread "main" java.sql.SQLException: JZ0SA: Prepared Statement: Input parameter not set, index: 0.
    at com.sybase.jdbc4.jdbc.SybConnection.getAllExceptions(Unknown Source)
    at com.sybase.jdbc4.jdbc.SybStatement.handleSQLE(Unknown Source)
    at com.sybase.jdbc4.jdbc.SybStatement.sendQuery(Unknown Source)
    at com.sybase.jdbc4.jdbc.SybPreparedStatement.sendQuery(Unknown Source)
    at com.sybase.jdbc4.jdbc.SybStatement.executeQuery(Unknown Source)
    at com.sybase.jdbc4.jdbc.SybPreparedStatement.executeQuery(Unknown Source)

使用的 JDBC 驱动程序(Maven 依赖):

<dependency>
            <groupId>com.sybase</groupId>
            <artifactId>jconn4</artifactId>
            <version>7.0</version>
</dependency>

【问题讨论】:

请添加执行语句。 虽然 JDBC 驱动程序应该对参数使用基于 1 的索引(JDBC 规范要求),但您是否尝试过使用基于 0 的索引(因为错误消息也使用基于 0 的索引)?在任何情况下,您都应该使用完整的异常堆栈跟踪更新您的问题,并指定您的 Sybase 驱动程序和 Sybase 服务器的 完整 版本。 您使用哪个 JDBC 驱动程序进行连接? 编辑了问题。是的,我尝试过使用基于 0 的索引 - 抛出了 ArrayOutOfBoundsException,因此必须使用基于 1 的索引。 来自您发布的代码:select * from view where off = ? and acc = ?view 是数据库表吗? offacc的数据类型是什么? 【参考方案1】:

我在使用 sybase iq 时遇到了同样的问题。 我在preparedStatement.execureQuery()语句之前添加了以下两行代码来解决这个问题。

 preparedStatement.setFetchSize(Integer.MAX_VALUE);
 preparedStatement.setFetchDirection(ResultSet.FETCH_FORWARD);

不确定这样做是否正确,但确实有效。

你可以设置 preparedStatement.setCursorName("SomeCursorName"); 这也解决了这个问题。 但在多线程环境下,您需要设置一个唯一的游标名称。可能正在使用随机数或其他东西,并且不要创建太多游标,将它们限制为将同时执行的并发线程数。

【讨论】:

【参考方案2】:

我使用了 jconn4 连接属性 LITERAL_PARAMS=t​​rue,它运行良好。小心,性能应该会受到影响。

当设置为“true”时,PreparedStatement 接口中的 setXXX 方法设置的任何参数都会在执行时插入到 SQL 语句中。如果设置为“false”,则在 SQL 语句中保留参数标记,并将参数值单独发送到服务器。

【讨论】:

这也解决了我使用 Sybase SQL Anywhere DB 的问题【参考方案3】:

stmt.setString(1, "260"); stmt.setString(2, "9050V");

数组索引以0开头不是吗?在您使用的 API 中,它不是基于零的索引吗?

【讨论】:

根据 Java 文档,PreparedStatement 索引从 1 开始 - 请参阅 docs.oracle.com/javase/7/docs/api/java/sql/… 这是一个答案吗?这应该是评论吗?

以上是关于PreparedStatement 不适用于 Java 中的 Sybase IQ的主要内容,如果未能解决你的问题,请参考以下文章

ResultSet.getNext() 不适用于 PreparedStatement

PreparedStatement 不适用于 Java 中的 Sybase IQ

htaccess 重定向适用于邮递员而不适用于 chrome (CORS)

Prepared Statement 中的绑定不适用于 Microsoft SQL Server JDBC 驱动程序 sqljdbc4.jar

JavaScript 数独求解器在某些板上陷入无限循环/不适用于所有板

PreparedStatement 与 Statement