基于湖库一体架构,统一管理结构化、半结构化与非结构化等多模态数据,一个系统承载事务处理、实时分析与 AI 工作负载。
批量插入数据报错:Parameter index out of bonds 的原因和解决方法
更新时间:2026-05-28 02:06
本文介绍批量插入数据报错:Parameter index out of bonds 的原因和解决方法。
问题现象
JDBC 侧配置了 rewriteBatchedStatements=TRUE 和 useServerPrepStmts=true,批量插入数据时报错:
Parameter index out of bounds. 4465 is not valid between 1 and 4464.
报错信息中的数字(4465)在不同批次执行时不固定,减少 batchsize 后报错不发生。
适用版本
OceanBase 数据库 V2.x、V3.x、V4.x 版本。
问题原因
当 JDBC 链接参数设置了 useServerPrepStmts=true 时,SQL 将使用 PS 协议(二进制协议),而单条 SQL 的参数上限为 65535。当 JDBC 连接参数配置了 rewriteBatchedStatements=true 并在应用中使用 batch 执行的方式对对同一张表循环多次进行 Insert 操作时,驱动会将多个 INSERT 语句转化为一个包含多个 VALUES 的 INSERT 语句。如果同时设置了 rewriteBatchedStatements=TRUE 和 useServerPrepStmts=true,并使用 batch 执行将多条 INSERT 合并为一条,当合并后的 INSERT 语句的变量个数超过了 65535,就会报错。
批量执行的 Java 代码示例。
public class BatchInsertExample {
public static void main(String[] args) {
// 假设已经获取到数据库连接connection
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
// 创建PreparedStatement对象,用于批量插入
String sql = "INSERT INTO t_insert (id, name, value) VALUES (?, ?, ?)";
preparedStatement = connection.prepareStatement(sql);
// 准备批量插入的数据
int batchSize = 1000; // 批量插入的条数
for (int i = 1; i <= batchSize; i++) {
preparedStatement.setInt(1, i);
preparedStatement.setString(2, "Country_" + i);
preparedStatement.setInt(3, 1000 * i);
preparedStatement.addBatch(); // 添加到批处理队列
}
// 执行批量插入
int[] affectedRows = preparedStatement.executeBatch();
// 输出受影响的行数
for (int affectedRow : affectedRows) {
System.out.println("Affected rows: " + affectedRow);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 关闭资源
try {
if (preparedStatement != null) {
preparedStatement.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
转化后的批量 INSERT 示例:
INSERT INTO t_insert (id, name, value) VALUES (?, ?, ?),(?, ?, ?),(?, ?, ?)...;
解决方法
方法一:缩小
batchsize,将一组batch的参数总量控制在 65535 之下。举例:如每行数据有 100 个参数,则
batch的大小要小于655(65535/100)个,以避免发生该报错。方法二:设置
useServerPrepStmts=false,使用文本协议,避免该问题。