java.sql.SQLException—— 索引中丢失 IN或OUT 参数————x

本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

原文链接:blog.ouyangsihai.cn >> java.sql.SQLException—— 索引中丢失 IN或OUT 参数————x

使用JDBC时,会有这么一个错误:java.sql.SQLException: 索引中丢失 IN或OUT 参数::x

如下示例中insertLog.execute();这行会抛出这个异常:

  • span style="font-size:14px;"String logSQL = "insert into tbl_obj(id, obj, type, cont, proposer, operator, date, remark) values(seq_tot.nextval, ?, ?, ?, ?, ?, SYSDATE, ?)";  
  • insertLog = conn.prepareStatement(logSQL);  
  • insertLog.setString(2, trace.getObj());  
  • insertLog.setString(3, trace.getType());  
  • insertLog.setString(4, trace.getCont());  
  • insertLog.setString(5, trace.getProposer());  
  • insertLog.setString(6, trace.getOperator());  
  • insertLog.setString(8, trace.getRemark());  
  • insertLog.execute();
  • 检索了一些帖子,对于这种问题,指出的原因很多,“全角半角引起;参数过多;配置文件和数据库字段类型不一致;或是数据库的索引问题等”。

    根据错误提示,和前辈种种的碰壁,归结为两点:

    (1) 索引是否有问题?(“索引中丢失”)

    (2) 字段赋值是否与数据库字段类型匹配?

    对于(1)的论证,查看这张表的索引,这张表是以ID作为主键,没有其他索引,因此只有一个主键索引,查看状态也是VALID的,没有错误:

    select index_name, status from user_indexes where table_name=’TBL_OBJ_TRACE’;  

  •   
  • INDEX_NAME                     STATUS  
  • ------------------------------ --------  
  • SYS_C0031302                   VALID  
  • 对于(2)的论证,

    首先看了trace的set/get方法中对字段类型的定义,都是String,对应库中的字段类型都是VARCHAR2,没有差别。

    其次再看setString,和VALUES中字段是对应的啊。其实问题就出在这了,看下setString方法的解释:

  • void java.sql.PreparedStatement.setString(int parameterIndex, String x) throws SQLException  
  • Sets the designated parameter to the given Java String value. The driver converts this to an SQL VARCHAR or LONGVARCHAR value (depending on the argument's size relative to the driver's limits on VARCHAR values) when it sends it to the database.  
  • Parameters:  
  • parameterIndex the first parameter is 1, the second is 2, ...  
  • x the parameter value  
  • Throws:  
  • SQLException - if parameterIndex does not correspond to a parameter marker in the SQL statement; if a database access error occurs or this method is called on a closed PreparedStatement
  • 可以看到第一个参数parameterIndex,参数索引,parameterIndex does not correspond to a parameter marker in the SQL statement(如果没有对应到SQL语句中的参数标识符),则会抛出SQLException异常。

    SQL语句中values(seq_tot.nextval, ?, ?, ?, ?, ?, SYSDATE, ?)的参数标识符一共6个,setString同样是6个,但顺序不对,setString中第一个参数的索引序号是要和SQL语句中是一致的,并不是SQL语句中这里VALUES字段的位置,而应该是SQL语句VALUES中参数标识符的序号。

    改为如下格式就对了:

  • String logSQL = "insert into tbl_obj(id, obj, type, cont, proposer, operator, date, remark) values(seq_tot.nextval, ?, ?, ?, ?, ?, SYSDATE, ?)";
  • insertLog = conn.prepareStatement(logSQL);  
  • insertLog.setString(1, trace.getObj());  
  • insertLog.setString(2, trace.getType());  
  • insertLog.setString(3, trace.getCont());  
  • insertLog.setString(4, trace.getProposer());  
  • insertLog.setString(5, trace.getOperator());  
  • insertLog.setString(6, trace.getRemark());  
  • insertLog.execute();  
  • 总结:

    JDBC的这个报错,提示信息很晦涩,但这个错误感觉是属于那种碰过一次之后,基本下次就能知道错误的范围,排查起来应该也比较顺畅了,例如:索引是否有问题、代码中的字段类型和表中字段类型是否一致、代码中使用的参数索引和SQL语句中的参数标识符是否一致(个数、顺序等)。‍

    本人花费半年的时间总结的《Java面试指南》已拿腾讯等大厂offer,已开源在github ,欢迎star!

    本文GitHub https://github.com/OUYANGSIHAI/JavaInterview 已收录,这是我花了6个月总结的一线大厂Java面试总结,本人已拿大厂offer,欢迎star

    原文链接:blog.ouyangsihai.cn >> java.sql.SQLException—— 索引中丢失 IN或OUT 参数————x


     上一篇
    外键为何要建索引? 外键为何要建索引?
      项目中,我们要求凡是有主子关系的表都要使用外键约束,来保证主子表之间关系的正确,不推荐由应用自己控制这种关系。 但发现有时开发人员提交SQL语句时未必会注意外键列需要定义索引,或者不清楚为什么外键列需要建立索引,网上一些所谓的“宝典”也
    下一篇 
    alter table新增字段操作究竟有何影响?(上篇) alter table新增字段操作究竟有何影响?(上篇)
    很久以前就有个疑问,见过一些表设计时会留出几个reverse的字段,目的是为了以后扩展,但此时设计的字段类型、长度等都是预计的,未来是否可用,不好说,那为什么会这么做呢?可能的原因是:“我现在设定好字段,需要的时候直接用就行了,不需要新增字