Я разместил аналогичную тему для администраторов БД StackExchange, но, возможно, здесь также будут дополнительные советы.
Мне нужно выполнить пакетную вставку данных в 2 таблицы, а в таблице 2 есть идентификатор FK из таблицы 1, поэтому мне нужно получить идентификатор, который был только что вставлен в таблицу 1, для каждой строки таблицы 2. Это с Postgres, из программы Java, используя jdbcTemplate.batchUpdate()
.
Table1 = USERS_T
Table2 = STUDY_PARTICIPANTS_T
имеет FK: USER_ID = USERS_T.ID
Проблема
Предположим, я использую Postgres currval('users_t_id_seq')
для получения значения последовательности, используемого Table1.
Один из способов пакетной вставки в 2 таблицы — последовательный, но это не сработает, потому что currval
будет иметь только идентификатор последней строки, поэтому все вставки Table2 будут перепутаны и будут иметь только одно последнее значение идентификатора Table1, которое равно неправильный.
// Part 1: Insert into USERS_T
batchInsertUsers(jdbcTemplate, batchInsertUsers);
// Part 2: Insert into STUDY_PARTICIPANTS_T
batchInsertStudyParticipants(jdbcTemplate, batchInsertUsers);
private void batchInsertUsers(JdbcTemplate jdbcTemplate, final List<UsersT> batchInsertUsers) {
String sql = "INSERT INTO USERS_T (ID, .., ..) " +
"VALUES (nextval('users_t_id_seq'), .., ..";
jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
//...
});
}
private void batchInsertStudyParticipants(JdbcTemplate jdbcTemplate, final List<UsersT> batchInsertUsers) {
String sql = "INSERT INTO STUDY_PARTICIPANTS_T (ID, USER_ID, ..) " +
"VALUES (nextval('study_participants_t_id_seq'),
currval('users_t_id_seq'), .., ..";
jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
//...
});
}
Другой способ «поймать» последний идентификатор — выполнить многострочную вставку для обеих таблиц, как показано ниже, — таким образом я мог бы поймать последнее значение последовательности USERS_T
.
Я следовал предложению здесь, где плакат рекомендовал многострочный INSERT с ;
.
Но в Postgres это дает следующую ошибку:
PSQLException: Too many update results were returned.
Я не могу использовать ;
для разделения своих однострочных ВСТАВОК, и это задокументировано здесь, https://www.postgresql.org/message-id/[email protected]
private void batchInsertAll(JdbcTemplate jdbcTemplate, final List<UsersT> batchInsertUsers) {
String sql = "INSERT INTO USERS_T (ID, .. ) " +
"VALUES (nextval('users_t_id_seq'), ..) " +
";" + // Note semicolon separating my multiline SQL
"INSERT INTO STUDY_PARTICIPANTS_T (ID, USER_ID, ..) " +
"VALUES (nextval('study_participants_t_id_seq'),
currval('users_t_id_seq'), .., ..";
jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
//...
});
}
Поэтому я не могу найти способ выполнить вставку из двух таблиц и поймать соответствующий идентификатор Table1 в этом процессе пакетной вставки Postgres.