我正在尝试在SqlServer和Oracle上进行批量插入,在以下测试代码中实现:
public class TesteBatch {
public static void main(String[] args) throws ClassNotFoundException {
Connection con = getConnection();
try {
con.setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
PreparedStatement psInsert = criaPs(con);
Date time = Calendar.getInstance().getTime();
for (int i = 1; i <= 50000; i++) {
try {
psInsert.setInt(1, i);
psInsert.setTimestamp(2, new Timestamp(time.getTime()));
psInsert.addBatch();
} catch (SQLException e) {
System.out.println("Erro inserindo " + i);
}
}
try {
int[] executeBatch = psInsert.executeBatch();
System.out.println(Arrays.toString(executeBatch));
psInsert.close();
con.close();
} catch (BatchUpdateException e) {
e.printStackTrace();
System.out.println(Arrays.toString(e.getUpdateCounts()));
} catch (SQLException e) {
e.printStackTrace();
}
}
private static PreparedStatement criaPs(Connection con) {
try {
return con.prepareStatement("insert into tester values (? , ?)");
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
private static Connection getConnection() {
try {
String url = "jdbc:oracle:thin:@BI_ENS:1521:xe";
Class.forName("oracle.jdbc.OracleDriver");
return DriverManager.getConnection(url,"xxxx", "xxxx");
} catch (ClassNotFoundException | SQLException e) {
throw new RuntimeException(e);
}
}
}
代码将数据插入到具有主键ID和时间戳的Tester表中。
我想要做的是以一种方式插入到数据库中,即使批处理中的某些数据已经存在,也会插入不存在的数据,因为违反了主键约束而抛出BatchUpdateException。
我正在测试一个包含50.000个条目的批次,其中50%已经在数据库中。
使用SqlServer,它按预期工作,抛出异常,但未复制的数据仍然插入到数据库中,最后所有50k注册表都在数据库中。
它在Oracle上不起作用,发生异常并且未插入批处理中的任何内容,即使数据库中不存在该数据也是如此。最后只有50%的批次存在。
有人可以解释为什么在Oracle上发生这种情况吗?有没有办法让它像在SqlServer上一样工作?
谢谢大家!
答案 0 :(得分:0)
根据oracle文档http://docs.oracle.com/cd/E11882_01/java.112/e16548/oraperf.htm#JJDBC28767,这是oracle processess批处理的方式:
注意: 批处理的执行始终会以生成错误的批处理的第一个元素停止。