MS SQL Server JDBC高版本批量插入118列VARCHAR字段报错求助
问题描述
向包含118列的SQL Server表插入数据时,使用mssql-jdbc-8.2.2.jre8.jar驱动一切正常,但升级到9.2.1至12.8.1版本的驱动后,会抛出java.sql.BatchUpdateException,提示第118列列长度无效。
关键现象:
- 仅当第118列为
VARCHAR或NVARCHAR类型时触发报错,改为FLOAT等数值类型则无问题 - 将该字段改为
NVARCHAR无法解决问题 - 新增一列
VARCHAR字段后,错误转移到第119列
插入SQL语句
insert into tt (CUSTOMER_ID,Value_date,_default,J_termek1,J_termek2,J_termek1_appl_pont,J_termek1_beh_pont,J_termek2_appl_pont,J_termek2_beh_pont,J_t ermek1_appl_intercept,J_termek1_appl_beta,J_termek1_beh_intercept,J_termek1_beh_beta,J_t ermek1_appl_weight,J_termek1_beh_weight,J_REL_def_STD,J_macro_correction,J_termek2_appl_intercept,J_termek2_appl_beta,J_termek2_beh_in tercept,J_termek2_beh_beta,J_termek2_appl_weight,J_termek2_beh_weight,J_termek1_weight,J_termek2_weight,L_termek1,L_ termek2,L_termek1_appl_pont,L_termek1_beh_pont,L_termek2_appl_pont,L_termek2_beh_pont,L_termek1_appl_intercept,L_termek1_appl_beta,L_t ermek1_beh_intercept,L_termek1_beh_beta,L_termek1_appl_weight,L_termek1_beh_weight,L_REL_def_STD,L_macro_correction, L_termek2_appl_intercept,L_termek2_appl_beta,L_termek2_beh_intercept,L_termek2_beh_beta,L_termek2_appl_weight,L_termek2_beh_weight,L_t ermek1_weight,L_termek2_weight,S_termek1,S_termek2,S_termek1_appl_pont,S_termek1_beh_pont,S_termek2_appl_pont,S_term ek2_beh_pont,S_termek1_appl_intercept,S_termek1_appl_beta,S_termek1_beh_intercept,S_termek1_beh_beta,S_termek1_appl_weight,S_termek1_b eh_weight,S_REL_def_STD,S_macro_correction,S_termek2_appl_intercept,S_termek2_appl_beta,S_termek2_beh_intercept,S_te rmek2_beh_beta,S_termek2_appl_weight,S_termek2_beh_weight,S_termek1_weight,S_termek2_weight,O_termek1,O_termek2,O_termek1_appl_pont,O_ termek1_beh_pont,O_termek2_appl_pont,O_termek2_beh_pont,O_termek1_appl_intercept,O_termek1_appl_beta,O_termek1_beh_i ntercept,O_termek1_beh_beta,O_termek1_appl_weight,O_termek1_beh_weight,O_REL_def_STD,O_macro_correction,O_termek2_appl_intercept,O_ter mek2_appl_beta,O_termek2_beh_intercept,O_termek2_beh_beta,O_termek2_appl_weight,O_termek2_beh_weight,O_termek1_weigh t,O_termek2_weight,H_termek1,H_termek2,H_termek1_appl_pont,H_termek1_beh_pont,H_termek2_appl_pont,H_termek2_beh_pont,H_termek1_appl_in tercept,H_termek1_appl_beta,H_termek1_beh_intercept,H_termek1_beh_beta,H_termek1_appl_weight,H_termek1_beh_weight,H_ REL_def_STD,H_macro_correction,H_termek2_appl_intercept,H_termek2_appl_beta,H_termek2_beh_intercept,H_termek2_beh_beta,H_termek2_appl_ weight,H_termek2_beh_weight,H_termek1_weight,H_termek2_weight,H_atlag_pd,spare3,BEH_PD,behpd,txt1) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,? ,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
报错堆栈
java.sql.BatchUpdateException: A rendszer érvénytelen oszlophosszt kapott a BCP-ügyféltől a következő oszlopazonosítóhoz: 118. at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeBatch(SQLServerPreparedStatement.java:2042) at SAS2SQL.writeToOutput(SAS2SQL.java:1098) at SAS2SQL.main(SAS2SQL.java:121)
英文报错翻译:
系统从BCP客户端收到以下列ID的无效列长度:118
插入逻辑代码
String str = stdin.readLine(); while (str != null) { counter++; //log(str); split(str); //log(arrayToText(elemek)); int k; for (int j = 0; j < fields.length; j++) { tip=fieldtypes[j]; textelem=elemek[j]; k=j+1; if (textelem==null)pstmt.setString(k,null); else { if (tip==Types.VARCHAR || tip==Types.NVARCHAR ) { pstmt.setString(k, textelem); //if (insertedRows<15) log("TXT: "+textelem); } if (tip==Types.INTEGER || tip==Types.BIGINT || tip==Types.SMALLINT || tip==Types.TINYINT ){ //log2("INT:"+Float.parseFloat()); if (textelem.trim().equals(".")) pstmt.setNull(k, java.sql.Types.FLOAT); else pstmt.setFloat(k, Float.parseFloat(textelem)); } if (tip==Types.FLOAT || tip==Types.NUMERIC || tip==Types.DOUBLE || tip==Types.DECIMAL ) { if (textelem.trim().equals(".")) pstmt.setNull(k, java.sql.Types.DOUBLE); else pstmt.setDouble(k, Double.parseDouble(textelem)); } if (tip==Types.DATE) { if (textelem.trim().equals(".")) pstmt.setNull(k, java.sql.Types.DATE); else pstmt.setDate(k, java.sql.Date.valueOf(textelem)); //log2("DATE:"+SASResultSet.getDate(j).toString()); } if (tip==Types.TIMESTAMP) { if (textelem.trim().equals(".")) pstmt.setNull(k, java.sql.Types.TIMESTAMP); else pstmt.setTimestamp(k,Timestamp.valueOf(textelem.trim())); } if (tip==Types.TIME) { if (textelem.trim().equals(".")) pstmt.setNull(k, java.sql.Types.TIME); else pstmt.setTime(k,Time.valueOf(textelem.trim())); //log2("TIME:"+SASResultSet.getTime(j).toString()); } } } str = stdin.readLine(); insertedRows++; pstmt.addBatch(); bulkcounter++; if (bulkcounter==batchSize){ pstmt.executeBatch(); pstmt.clearBatch(); bulkcounter=0; if (monitor)log(getTime()+" / "+insertedRows); } //pstmt.executeUpdate(); } if (bulkcounter!=0) { pstmt.executeBatch(); pstmt.clearBatch(); if (monitor)log(getTime()+" / "+insertedRows); } //if (siker==0) log(""+counter+". sor beszúrása sikertelen"); sqlServerConnection.commit(); //outputConnection.commit(); stdin.close(); pstmt.close(); log("Number of inserted rows: "+insertedRows);
解决方案
这个问题是mssql-jdbc驱动在9.x及以后版本中,对批量插入时字符串类型字段的长度校验逻辑发生变化,字段数量较多时易触发索引偏移或长度计算错误。可尝试以下解决方法:
显式指定字符串参数长度
设置字符串参数时,使用带长度参数的重载方法,确保驱动正确识别参数长度:pstmt.setString(k, textelem, textelem.length());也可提前获取数据库字段的定义长度,传入对应值。
禁用BCP批量插入模式
新版本驱动默认启用BCP优化批量插入,字段数量较多时可能出现兼容性问题。在JDBC URL中添加参数关闭该模式:jdbc:sqlserver://<server>:<port>;databaseName=<db>;useBcpBatch=false;回退驱动版本或提交bug
若上述方法无效,可暂时回退到8.2.2版本驱动,或向Microsoft提交兼容性问题等待官方修复。检查字符串内容
确认第118列的字符串是否包含不可见字符、超长字符,或因编码转换导致的长度异常(如Unicode字符被错误计算为单字节长度)。
内容的提问来源于stack exchange,提问作者Laszlo voros
相关产品推荐
相关产品推荐

