JDBC 批量插入、返回 ID
JDBC Batch INSERT, RETURNING IDs
有什么方法可以使用 RETURNING INTO 获取受影响行的值吗?
我必须插入相同的行 x 次并获取插入行的 ID。
查询如下所示:
public static final String QUERY_FOR_SAVE =
"DECLARE " +
" resultId NUMBER ; " +
"BEGIN " +
" INSERT INTO x " +
" (a, b, c, d, e, f, g, h, i, j, k, l, m) " +
" values (sequence.nextVal, :a, :b, :c, :d, :e, :f, :g, :h, :i, :j, :k, :l) " +
" RETURNING a INTO :resultId;" +
"END;";
现在我可以使用 addBatch
在 JAVA 循环中将此查询添加到批处理中
IntStream.range(0, count)
.forEach(index -> {
try {
setting parameters...
cs.addBatch();
} catch (SQLException e) {
e.printStackTrace();
}
});
cs.executeBatch();
有什么方法可以像这样从批处理中 return 数组或列表吗?
我可以只使用 sql 执行那些插入 x 次,但在这种情况下我也想知道如何 return 一个 ids 数组。
提前致谢
我假设这是关于 Oracle 的。据我所知,这是不可能的,但您可以在匿名 PL/SQL 块中使用 FORALL
运行 批量插入,如我最近写的这篇文章中所述:
https://blog.jooq.org/2018/05/02/how-to-run-a-bulk-insert-returning-statement-with-oracle-and-jdbc/
这是文章中的一个自包含的 JDBC 示例,它插入一个值数组并将结果批量收集回 JDBC 客户端:
try (Connection con = DriverManager.getConnection(url, props);
Statement s = con.createStatement();
// The statement itself is much more simple as we can
// use OUT parameters to collect results into, so no
// auxiliary local variables and cursors are needed
CallableStatement c = con.prepareCall(
"DECLARE "
+ " v_j t_j := ?; "
+ "BEGIN "
+ " FORALL j IN 1 .. v_j.COUNT "
+ " INSERT INTO x (j) VALUES (v_j(j)) "
+ " RETURNING i, j, k "
+ " BULK COLLECT INTO ?, ?, ?; "
+ "END;")) {
try {
// Create the table and the auxiliary types
s.execute(
"CREATE TABLE x ("
+ " i INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,"
+ " j VARCHAR2(50),"
+ " k DATE DEFAULT SYSDATE"
+ ")");
s.execute("CREATE TYPE t_i AS TABLE OF NUMBER(38)");
s.execute("CREATE TYPE t_j AS TABLE OF VARCHAR2(50)");
s.execute("CREATE TYPE t_k AS TABLE OF DATE");
// Bind input and output arrays
c.setArray(1, ((OracleConnection) con).createARRAY(
"T_J", new String[] { "a", "b", "c" })
);
c.registerOutParameter(2, Types.ARRAY, "T_I");
c.registerOutParameter(3, Types.ARRAY, "T_J");
c.registerOutParameter(4, Types.ARRAY, "T_K");
// Execute, fetch, and display output arrays
c.execute();
Object[] i = (Object[]) c.getArray(2).getArray();
Object[] j = (Object[]) c.getArray(3).getArray();
Object[] k = (Object[]) c.getArray(4).getArray();
System.out.println(Arrays.asList(i));
System.out.println(Arrays.asList(j));
System.out.println(Arrays.asList(k));
}
finally {
try {
s.execute("DROP TYPE t_i");
s.execute("DROP TYPE t_j");
s.execute("DROP TYPE t_k");
s.execute("DROP TABLE x");
}
catch (SQLException ignore) {}
}
}
有什么方法可以使用 RETURNING INTO 获取受影响行的值吗? 我必须插入相同的行 x 次并获取插入行的 ID。
查询如下所示:
public static final String QUERY_FOR_SAVE =
"DECLARE " +
" resultId NUMBER ; " +
"BEGIN " +
" INSERT INTO x " +
" (a, b, c, d, e, f, g, h, i, j, k, l, m) " +
" values (sequence.nextVal, :a, :b, :c, :d, :e, :f, :g, :h, :i, :j, :k, :l) " +
" RETURNING a INTO :resultId;" +
"END;";
现在我可以使用 addBatch
在 JAVA 循环中将此查询添加到批处理中 IntStream.range(0, count)
.forEach(index -> {
try {
setting parameters...
cs.addBatch();
} catch (SQLException e) {
e.printStackTrace();
}
});
cs.executeBatch();
有什么方法可以像这样从批处理中 return 数组或列表吗? 我可以只使用 sql 执行那些插入 x 次,但在这种情况下我也想知道如何 return 一个 ids 数组。
提前致谢
我假设这是关于 Oracle 的。据我所知,这是不可能的,但您可以在匿名 PL/SQL 块中使用 FORALL
运行 批量插入,如我最近写的这篇文章中所述:
https://blog.jooq.org/2018/05/02/how-to-run-a-bulk-insert-returning-statement-with-oracle-and-jdbc/
这是文章中的一个自包含的 JDBC 示例,它插入一个值数组并将结果批量收集回 JDBC 客户端:
try (Connection con = DriverManager.getConnection(url, props);
Statement s = con.createStatement();
// The statement itself is much more simple as we can
// use OUT parameters to collect results into, so no
// auxiliary local variables and cursors are needed
CallableStatement c = con.prepareCall(
"DECLARE "
+ " v_j t_j := ?; "
+ "BEGIN "
+ " FORALL j IN 1 .. v_j.COUNT "
+ " INSERT INTO x (j) VALUES (v_j(j)) "
+ " RETURNING i, j, k "
+ " BULK COLLECT INTO ?, ?, ?; "
+ "END;")) {
try {
// Create the table and the auxiliary types
s.execute(
"CREATE TABLE x ("
+ " i INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,"
+ " j VARCHAR2(50),"
+ " k DATE DEFAULT SYSDATE"
+ ")");
s.execute("CREATE TYPE t_i AS TABLE OF NUMBER(38)");
s.execute("CREATE TYPE t_j AS TABLE OF VARCHAR2(50)");
s.execute("CREATE TYPE t_k AS TABLE OF DATE");
// Bind input and output arrays
c.setArray(1, ((OracleConnection) con).createARRAY(
"T_J", new String[] { "a", "b", "c" })
);
c.registerOutParameter(2, Types.ARRAY, "T_I");
c.registerOutParameter(3, Types.ARRAY, "T_J");
c.registerOutParameter(4, Types.ARRAY, "T_K");
// Execute, fetch, and display output arrays
c.execute();
Object[] i = (Object[]) c.getArray(2).getArray();
Object[] j = (Object[]) c.getArray(3).getArray();
Object[] k = (Object[]) c.getArray(4).getArray();
System.out.println(Arrays.asList(i));
System.out.println(Arrays.asList(j));
System.out.println(Arrays.asList(k));
}
finally {
try {
s.execute("DROP TYPE t_i");
s.execute("DROP TYPE t_j");
s.execute("DROP TYPE t_k");
s.execute("DROP TABLE x");
}
catch (SQLException ignore) {}
}
}