我有一个奇怪的问题与Dbutils,我想运行一个参数化的更新SQL,我提供了正确数量的参数,但dbutils正在修改时间戳列的名称通过更改它的名称修改它
当时间戳列名是一个字母表
java.sql.SQLException:错误的参数数量:预计4,被给予5查询:UPDATE WEATHER_2 SET WEATHER =? ,O = TO_TIMESTAMP(?,'YYYY-MM-DD HH24:MI:SS.FF'),HUMIDITY =? ,TEMP =? WHERE ID =? 参数:[804,2015-06-05 17:21:05.809,16.0,25.15,1347927]
当时间戳列的名字是正常的..它会省略第二个字母表
java.sql.SQLException:ORA-00904:“OSTIME”:无效标识符查询:UPDATE WEATHER_2 SET WEATHER =? ,OBSTIME = TO_TIMESTAMP(?,'YYYY-MM-DD HH24:MI:SS.FF'),HUMIDITY =? ,TEMP =? WHERE ID =? 参数:[804,2015-06-05 17:27:46.139,16.0,25.15,1347927]
这可能是一个数据库的东西? 这也只发生在types为Date或Timestamp的列上。
我有一个类似的问题。 我认为这是Oracle JDBC 7驱动程序(ojdbc7.jar)中的一个错误。 该错误可能在PreparedStatement.getParameterMetaData方法中。
Apache DBUtils在内部使用此方法。 所以它不会是DBUtils的一个bug,而是来自Oracle 12c分发的Oracle JDBC驱动程序的一个bug。
如果您使用Oracle 11g ojdbc6.jar驱动程序,相同的查询可能会正常工作。 它至少为我工作。
如果您想查看Oracle ojdbc7.jar驱动程序在内部如何错误处理查询,则可以使用oracle.jdbc.driver.OracleParameterMetaDataParser类中包含的主要方法。 尝试这个:
java -classpath ojdbc7.jar oracle.jdbc.driver.OracleParameterMetaDataParser“YOUR SQL HERE”
例如
java -classpath ojdbc7.jar oracle.jdbc.driver.OracleParameterMetaDataParser“UPDATE PERSON SET LASTNAME = ?, FIRSTNAME =?WHERE PERSONID =?”
输出是您的SQL Sentence解析并转换为由驱动程序在内部使用的SQL查询来标识参数数据类型:
SQL:UPDATE PERSON SET LASTNAME =:1,FIRSTNAME =:2 WHERE PERSONID =:3 SqlKind:UPDATE,Parameter Count = 3参数SQL:SELECT LASTNAME,F,PERSONID FROM PERSON
但正如您在示例中所看到的,FIRSTNAME被错误地解析为“F”。
使用你在问题中提到的查询之一,结果是其中一个参数就消失了…所以解析器说“5”参数,但是用于获取数据类型的内部查询确实只有“4”(HUMIDITY has去了SELECT)。
java -classpath ojdbc7.jar oracle.jdbc.driver.OracleParameterMetaDataParser“UPDATE WEATHER_2 SET WEATHER =?,OBSTIME = TO_TIMESTAMP(?,'YYYY-MM-DD HH24:MI:SS.FF'),HUMIDITY =?,TEMP =? WHERE ID =?“
输出:
SQL:UPDATE WEATHER_2 SET WEATHER =:1,OBSTIME = TO_TIMESTAMP(:2,'YYYY-MM-DD HH24:MI:SS.FF'),HUMIDITY =:3,TEMP =:4 WHERE ID = 5
SqlKind:更新,参数计数= 5
参数SQL:SELECT WEATHER,OBSTIME,TEMP,ID FROM WEATHER_2
如何解决? 不知道,但正如我上面所说,使用Oracle 11g ojdbc6.jar驱动程序,相同的查询工作(甚至连接到一个Oracle 12c数据库…)。
行为是相当随机的。 它看起来像取决于UPDATE中使用的列的第一个字母。 如果它始于F和H总是失败,但我不知道是否还有其他条件。
oracle 12.1.0.1.0 jdbc oracle.jdbc.driver.OracleParameterMetaDataParser很烂!
在我的测试中:
oracle.jdbc.driver.OracleParameterMetaDataParser.main(new String [] {“update test set ORDX =?,A123 =?,FABCDEFG =?where A2C =?”})
==>
SQL:更新测试集ORDX = 1,A123 = 2,FABCDEFG =:3其中A2C =:4 SqlKind:UPDATE,参数计数= 4参数SQL:SELECT OX,A23,F,AC FROM测试
字段以“O”开始将修剪1-2个字符
字段以“F”开始将全部修剪
字段以“A”开头将修剪1个字符
在oralce 12.1.0.2.0上还有问题:现场以“F”开头将全部修剪
http://www.oracle.com/technetwork/database/features/jdbc/default-2280470.html
我遇到同样的问题,使用DBUtils并从ojdbc6升级到ojdbc7。 然后我意识到这是一个参数错误,所以我自己填写。 如下所示:
更新():
Connection conn = dataSource.getConnection(); PreparedStatement ps = conn.prepareStatement(sql.toUpperCase()); this.fillStatement(ps, param); int rs = ps.executeUpdate(); ps.close(); conn.close();
fillStatement():
private void fillStatement(PreparedStatement stmt, Object... params) throws SQLException { int i = 1; for (Object o: params){ fill(stmt, i, o); i ++; } } private void fill(PreparedStatement stmt, int index, Object param) throws SQLException { if (param == null) { stmt.setObject(index, null); } else if (param instanceof String) { stmt.setString(index, (String) param); } else if (param instanceof Boolean) { stmt.setBoolean(index, (Boolean) param); } else if (param instanceof Integer) { stmt.setInt(index, (Integer) param); } else if (param instanceof Long) { stmt.setLong(index, (Long) param); } else if (param instanceof Double) { stmt.setDouble(index, (Double) param); } else if (param instanceof Float) { stmt.setFloat(index, (Float) param); } else if (param instanceof Short) { stmt.setShort(index, (Short) param); } else if (param instanceof Clob) { stmt.setClob(index, (Clob) param); } else if (param instanceof Blob) { stmt.setBlob(index, (Blob) param); } else if (param instanceof java.sql.Timestamp) { stmt.setTimestamp(index, (java.sql.Timestamp) param); } else if (param instanceof BigDecimal) { stmt.setBigDecimal(index, (BigDecimal) param); }else if (param instanceof java.sql.Time) { stmt.setTime(index, (java.sql.Time) param); } else if (param instanceof java.sql.Date) { stmt.setDate(index, (java.sql.Date) param); } else if (param instanceof Date) { stmt.setDate(index, new java.sql.Date(((Date) param).getTime())); } else { stmt.setObject(index, param); } }