PreparedStatement 中的列索引无效

Posted

技术标签:

【中文标题】PreparedStatement 中的列索引无效【英文标题】:Invalid column index in preparedStatement 【发布时间】:2014-12-11 18:22:39 【问题描述】:

我正在尝试在数据库表中插入一个值,但一直遇到 Invalid Column Index 错误。

这是一个代码示例:

        String insertNewAlarmStat =
            "insert into alarmes (id_alarm, alarm_key, id_notif, sever, urgency, date_hour_start, date_hour_modif, date_hour_end, " +
                    "state, state_rec, date_hour_rec,  id_user_rec, id_system_rec, " +
                    "type, cause, " +
                    "num_events, id_entity_g, type_entity_g, " +
                    "desc_entity_g, problem, " +
                    "time_urg_act, max_urg_act, time_end, time_arq, lim, rec_oblig, dn, num_events_ps, id_alarm_o, id_notif_o, text_ad, domain, date_hour_reg) " +
                    "values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, SYSDATE, SYSDATE, SYSDATE, SYSDATE, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, SYSDATE)";
    PreparedStatement prpstmt = null ;
    try 
        prpstmt = conn.prepareStatement(insertNewAlarmStat);

        prpstmt.setInt(1, randomNumberGenerator());
        prpstmt.setString(2, UUID.randomUUID().toString());
        prpstmt.setString(3, UUID.randomUUID().toString());
        prpstmt.setInt(4, randomNumberGenerator());
        prpstmt.setInt(5, 8);
        prpstmt.setInt(6, 8524);
        prpstmt.setString(7, UUID.randomUUID().toString());
        prpstmt.setString(8, UUID.randomUUID().toString());
        prpstmt.setString(9, UUID.randomUUID().toString());
        prpstmt.setString(10, UUID.randomUUID().toString());
        prpstmt.setString(11, "KABOOM");
        prpstmt.setInt(12, 8);
        prpstmt.setDate(13, getCurrentDate());
        prpstmt.setDate(14, getCurrentDate());
        prpstmt.setDate(15, getCurrentDate());
        prpstmt.setDate(16, getCurrentDate());
        prpstmt.setInt(17, 43);
        prpstmt.setString(18, UUID.randomUUID().toString());
        prpstmt.setString(19, UUID.randomUUID().toString());
        prpstmt.setString(20, UUID.randomUUID().toString());
        prpstmt.setString(21, UUID.randomUUID().toString());
        prpstmt.setInt(22, 2);
        prpstmt.setInt(23, 224);
        prpstmt.setInt(24, 2);
        prpstmt.setInt(25, 224);            
        prpstmt.setInt(26, 2);
        prpstmt.setInt(27, 4);          
        prpstmt.setInt(28, 2);  
        prpstmt.setString(29, null);
        prpstmt.setString(30, UUID.randomUUID().toString());
        prpstmt.setString(31, UUID.randomUUID().toString());            
        prpstmt.setInt(32, 2);  

        prpstmt.execute();

     catch (SQLException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
    

我尝试将 prpstmt 从 13 删除到 16,但它抱怨这些索引丢失,我也尝试了其他东西,但我无法让它工作。

我做错了什么?

【问题讨论】:

您正在准备 32 个值,但您有 27 个?我不知道这就是 java 准备好的语句的工作原理 如果我数正确的话,有 28 个。此外,使用(可能)伪随机数设置各种数据库 ID 是高度值得怀疑的。 另外,这段代码中有很多个“幻数”。 他们应该是魔法诶 【参考方案1】:

删除

prpstmt.setDate(13, getCurrentDate());
prpstmt.setDate(14, getCurrentDate());
prpstmt.setDate(15, getCurrentDate());
prpstmt.setDate(16, getCurrentDate());

而不是 17,再次从 13 开始..

?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, SYSDATE, SYSDATE, SYSDATE, SYSDATE, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, SYSDATE

1、2、3、4、5、6、7、8、9、10、11、12、SYSDATE、SYSDATE、SYSDATE、SYSDATE、13、14....等

【讨论】:

此答案已被标记为低质量答案。请在您的帖子中发表一些解释。 执行此操作后,我不断收到 ORA-00932:数据类型不一致:预期 DATE 得到 NUMBER 这是一个预言机错误。尝试将相同的参数作为输入传递给过程并从 PL/SQL 开发人员或您使用的任何客户端运行它。然后你可以调试哪个输入给你那个错误。【参考方案2】:

此插入语句中有 33 列。有 33 个值——28 个 ? 占位符和 5 个字面值 (sysdate)。 setXYZ 方法中的索引是指? 占位符的索引,而不是插入语句值的索引。

对于sysdate 值,您无需执行任何操作,因此请删除对setDate 的调用。但是对于前 4 个sysdates 之外的值,您只需要使用下一个值,即13,而不是17

prpstmt.setInt(1, randomNumberGenerator());
// snip
prpstmt.setInt(12, 8);
// calls to `setDate(13-16, getCurrentDate());` removed
prpstmt.setInt(13, 43);  // changed 17 to 13
// snip
prpstmt.setInt(28, 2);   // changed 32 to 28

什么是sysdate

sysdate 是一个 Oracle 函数,它返回当前的 date/timestamp,相当于 Java 中的 Calendar.getInstance()。对于JDBC,它是一个已在插入语句中提供的值。

【讨论】:

你能解释一下什么是sysdate吗?所以我可以完全理解你的答案,以便给你投票 我猜是系统日期? @KickButtowski sysdate 是一个返回当前日期/时间戳的 Oracle 函数,相当于 Java 中的 Calendar.getInstance()。就 JDBC 而言,它是插入语句中已提供的值。 执行此操作后,我有 ORA-00932:不一致的数据类型:预期 DATE 得到 NUMBER【参考方案3】:

你的查询String包含28个问号,我写了一个程序给你算

String str = "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, SYSDATE, SYSDATE, SYSDATE, "
    + "SYSDATE, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, SYSDATE)";
int count = 0;
for (char ch : str.toCharArray()) 
    if (ch == '?') 
        count++;
    

System.out.println(count);

因此,您不能绑定 32 个参数。我认为你的

 prpstmt.setDate(13, getCurrentDate());
 prpstmt.setDate(14, getCurrentDate());
 prpstmt.setDate(15, getCurrentDate());
 prpstmt.setDate(16, getCurrentDate());

在查询中被硬编码为SYSDATE。所以,去掉查询中间的四个SYSDATE(s)

"(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, "
+ "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, SYSDATE)";

你会有 32 个。

【讨论】:

以上是关于PreparedStatement 中的列索引无效的主要内容,如果未能解决你的问题,请参考以下文章

java.sql.SQLException:无效的列索引

匿名plsql块中的列索引无效[重复]

java.sql.SQLException: 无效的列索引

java.sql.SQLException: 无效的列索引

java.sql.SQLException: 无效的列索引

无效的列索引错误 - 无法解决问题