将一个数据库的多个联合表格中的查询结果复制到另一个数据库的最佳做法?

时间:2018-05-08 09:02:34

标签: java sql postgresql

  • 我有几个连接表,其中包含一个名为'sourceDB'的postgreSQL(版本9.6.4)数据库中的大量数据。
  • 我需要查询所有这些表并将结果从'sourceDB'复制到名为'destinationDB'的第二个(空)postgreSQL(也是版本9.6.4)数据库,该数据库没有数据库方案,但应该有与'sourceDB'相同的数据库方案。
  • 两个数据库都在同一主机系统上,必须通过JAVA应用程序进行控制。

到目前为止我尝试的是:

  1. 确定'sourceDB'的数据库方案。
  2. 对'destinationDB'上的'sourceDB'的所有现有表运行“CREATE TABLE IF NOT EXISTS ...”语句,以确保两个数据库具有相同的数据库方案。这很好用!
  3. 为每个表(在'sourceDB'上)运行数据库查询(SELECT DISTINCT ...)以获取数据,然后在每个表运行之后使用'copyTableData'函数将结果(通过INSERT INTO)复制到' destinationDB':
  4. 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++;
                }
    
    1. 现在将查询结果复制到'destinationDB'(通过INSERT INTO):
    2. 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异常,有一行已经包含值(null,null,null,null,null,null)。我不知道如何解释......:

      • 你认为第二个INSERT INTO的问题是INSERT INTO是否存在已经存在的主键如d_id的问题,因为第一个copyTableData函数调用(就'table1'而言)?
      • 或INSERT INTO确实存在Null值问题吗?

0 个答案:

没有答案