Пакетная вставка Postgres в 2 таблицы, где для таблицы 2 требуется идентификатор из таблицы 1: мультивставка с «;» не разрешено

Я разместил аналогичную тему для администраторов БД 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.


person gene b.    schedule 24.02.2020    source источник