- У меня есть несколько объединенных таблиц с большим количеством данных в одной базе данных postgreSQL (версия 9.6.4) под названием «sourceDB».
- Мне нужно запросить все эти таблицы и скопировать результаты из 'sourceDB' во вторую (пустую) базу данных postgreSQL (также версии 9.6.4) с именем 'destinationDB', которая не имеет схемы базы данных, но должна иметь та же схема базы данных, как 'sourceDB'.
- Обе базы данных находятся в одной хост-системе и должны управляться через приложение JAVA.
То, что я до сих пор пробовал, это:
- Определите схему базы данных 'sourceDB'.
- Запустите оператор «CREATE TABLE IF NOT EXISTS ...» для всех существующих таблиц «sourceDB» в «destinationDB», чтобы убедиться, что обе базы данных имеют одинаковую схему базы данных. Это работает очень хорошо!
- Запустите запрос БД (SELECT DISTINCT ...) для каждой таблицы (в «sourceDB»), чтобы получить данные, и после этого запустите для каждой таблицы функцию «copyTableData», чтобы скопировать результаты (через INSERT INTO) в « destinationDB ':
JAVA-код:
String[] tables = new String[]{
"table1",
"table2_table4",
"table3_addresses",
"table4",
"table5",
"table6",
"table7",
"table8",
"table9",
"table10",
"table11",
"table12"
};
int counter = 0;
for( String table : tables ){
int copyProcess = 100/tables.length*counter;
if (counter == 0){
System.out.println(importApp.getDateTime() +
"Initiating Import - Importing table '" + table + "'");
} else {
System.out.println(importApp.getDateTime() +
copyProcess + " % completed - Importing table '" + table + "'");
}
getDataFromSrcDB = "SELECT DISTINCT " + table + ".* " +
"FROM table1 " +
"FULL JOIN table2_table4 " +
"ON table2_table4.d_id=table1.d_id " +
"FULL JOIN table3_addresses " +
"ON table3_addresses.d_id=table2_table4.d_id " +
"FULL JOIN table4 " +
"ON table4.p_id=table2_table4.p_id " +
"FULL JOIN table5 " +
"ON table5.d_id=table1.d_id " +
"FULL JOIN table6 " +
"ON table6.d_id=table1.d_id " +
"FULL JOIN table7 " +
"ON table7.d_id=table1.d_id " +
"FULL JOIN table8 " +
"ON table8.d_id=table1.d_id " +
"FULL JOIN table9 " +
"ON table9.d_id=table1.d_id " +
"FULL JOIN table10 " +
"ON table10.id=table6.id " +
"FULL JOIN table11 " +
"ON table11.d_id=table1.d_id " +
"FULL JOIN table12 " +
"ON table12.a_id=table3_addresses.a_id " +
"WHERE ST_Intersects(ST_MakeEnvelope(" +
myApp.minLong + "," +
myApp.minLat + "," +
myApp.maxLong + "," +
myApp.maxLat + ",4326), geom :: GEOMETRY) OR " +
"ST_Intersects(ST_MakeEnvelope(" +
myApp.minLong + "," +
myApp.minLat + "," +
myApp.maxLong + "," +
myApp.maxLat + ",4326), CAST(table5.location AS GEOMETRY))";
myApp.copyTableData(dbConnOnSrcDB, dbConnOnDestDB, getDataFromSrcDB, table);
counter++;
}
- Теперь скопируйте результаты запроса в 'destinationDB' (через INSERT INTO):
JAVA-код:
public void copyTableData(Connection dbConnOnSrcDB, Connection dbConnOnDestDB, String sqlQueryOnSrcDB, String tableNameOnDestDB) throws SQLException {
try (
PreparedStatement prepSqlStatmOnSrcDB = dbConnOnSrcDB.prepareStatement(sqlQueryOnSrcDB);
ResultSet sqlResultsFromSrcDB = prepSqlStatmOnSrcDB.executeQuery()
) {
ResultSetMetaData sqlMetaResults = sqlResultsFromSrcDB.getMetaData();
// Stores the query results
List<String> columnsOfQuery = new ArrayList<>();
// Store query results
for (int i = 1; i <= sqlMetaResults.getColumnCount(); i++)
columnsOfQuery.add(sqlMetaResults.getColumnName(i));
try (
PreparedStatement prepSqlStatmOnDestDB = dbConnOnDestDB.prepareStatement(
"INSERT INTO " + tableNameOnDestDB +
" (" + columnsOfQuery.stream().collect(Collectors.joining(", ")) + ") " +
"VALUES (" + columnsOfQuery.stream().map(c -> "?").collect(Collectors.joining(", ")) + ")")
) {
final int batchSize = 1000;
int count = 0;
while (sqlResultsFromSrcDB.next()) {
for (int i = 1; i <= sqlMetaResults.getColumnCount(); i++) {
prepSqlStatmOnDestDB.setObject(i, sqlResultsFromSrcDB.getObject(i));
}
prepSqlStatmOnDestDB.addBatch();
if (++count % batchSize == 0) {
prepSqlStatmOnDestDB.executeBatch();
}
}
// Insert remaining records
prepSqlStatmOnDestDB.executeBatch();
prepSqlStatmOnDestDB.close();
prepSqlStatmOnSrcDB.close();
}
}
}
Моя проблема в том, что я не настолько опытен в (Postgres) SQL, поэтому я не уверен, что мой подход хорош (эффективен / эффективен), соответственно, какова на самом деле лучшая практика для достижения этого?
Другая проблема заключается в том, что первый вызов функции copyTableData (в терминах 'table1') работает довольно хорошо, но если функция copyTableData вызывается во второй раз (для 'table2' или 'table3', или ...) Я получаю исключение JAVA, что есть строка, которая уже содержит значения (ноль, ноль, ноль, нуль, ноль, ноль). Я не уверен, как это интерпретировать ...:
- Как вы думаете, проблема во втором INSERT INTO в том, что у INSERT INTO есть проблемы с уже существующими первичными ключами, такими как d_id, из-за первого вызова функции copyTableData (в терминах 'table1')?
- Или у INSERT INTO действительно есть проблемы с нулевыми значениями?