Как создать базу данных h2 из некоторых полей файла CSV - PullRequest
8 голосов
/ 01 марта 2011

Я хотел бы создать новую встроенную базу данных h2 из файла CSV.Вот фрагмент файла csv

Страна, Город, AccentCity, Регион, Население, Широта, Долгота

ad, aixovall, Aixovall, 06, 42.4666667,1.4833333

ad, Андорра, Андорра, 07, 42.5,1.5166667

ad, Андорра-ла-Велья, Андорра-ла-Велья, 07,20430,42.5,1.5166667

ad, andorra-vieille, Андорра-Вьей, 07, 42,5,1,5166667

ad, andorre, Андорра, 07, 42,5,1.5166667

Я не хочу получать все поляCSV-файл.На самом деле, я хочу их все, кроме полей City и Region .

И еще, я хочу вставить содержимое файла csv в базу данных ТОЛЬКО ЕСЛИсодержимое POPULATION не пусто.

Таким образом, в приведенном выше примере csv мы должны только вставить 3-ю строку в таблицу h2 WORLDCITIES, потому что указано ее поле "население".

Вот фрагмент кода, который я написал.Но, как видите, этого пока недостаточно:

conn = DriverManager.getConnection(connectionURL, connectionProps);
Statement stmt = conn.createStatement();
stmt.execute("CREATE TABLE WORLDCITIES"
        + " AS SELECT COUNTRY, ACCENTCITY, POPULATION, LATITUDE, LONGITUDE"
        + " FROM CSVREAD('snippet.csv'));

И если я правильно понимаю, CSVREAD создает поля, используя тип VARCHAR, но я хочу такие вещи:

Страна VARCHAR (3), ACCENTCITY VARCHAR (40), поплавок населения, поплавок роста, поплавок долготы

Заранее спасибо за помощь.

Ответы [ 3 ]

10 голосов
/ 02 марта 2011

Вы можете добавить определения столбцов в CREATE TABLE как , задокументированные , и объединить их с предложением WHERE.Обратите внимание, что использование CREATE TABLE AS SELECT немного быстрее, чем отдельные операторы CREATE TABLE и INSERT INTO (не уверен, что скорость очень важна для вас):

CREATE TABLE WORLDCITIES(
  COUNTRY VARCHAR(3), 
  ACCENTCITY VARCHAR(40), 
  POPULATION FLOAT, 
  LATITUDE FLOAT, 
  LONGITUDE FLOAT)
AS SELECT 
  COUNTRY, 
  ACCENTCITY, 
  POPULATION, 
  LATITUDE, 
  LONGITUDE
FROM CSVREAD('snippet.csv') 
WHERE POPULATION IS NOT NULL;
3 голосов
/ 02 марта 2011

наконец, я поступил так, как вы советовали. Я ставлю только те части кода, которые, как мне кажется, больше связаны с вопросом:)

`

private final String createTableString = ""
    + "CREATE TABLE IF NOT EXISTS " + _tableName
    + " ("
    + "id INT UNSIGNED NOT NULL AUTO_INCREMENT, "
    + "country VARCHAR(3) NOT NULL, "
    + "city VARCHAR(40) NOT NULL, "
    + "region VARCHAR (5) NOT NULL, "
    + "population FLOAT NOT NULL, "
    + "latitude FLOAT NOT NULL, "
    + "longitude FLOAT NOT NULL, "
    + "PRIMARY KEY(id)"
    + " );";

private final String insertString = ""
    + "INSERT INTO " + _tableName
    + " (country, city, region, population, latitude, longitude) "
    + "VALUES (?,?,?,?,?,?)"
    + ";";

public void go() throws IOException, SQLException {

    loadDriver();
    Connection conn = null;
    Properties connectionProps = new Properties();
    connectionProps.put("user", "");
    connectionProps.put("password", "");
    String connectionURL = _protocol + _subprotocol + _dbName + _dbSettings;
    ResultSet rs = null;

    try {
        conn = DriverManager.getConnection(connectionURL, connectionProps);
        logger.info("Connected to {} database.", _dbName);

        conn.setAutoCommit(false);
        Savepoint savept1 = conn.setSavepoint();

        Statement stmt = conn.createStatement();
        try {
            stmt.execute(createTableString);
            logger.info("The table '{}' created successfully", _tableName);
        } catch (SQLException sqle) {
            logger.error("Error while creating the table '{}'", _tableName);
            printSQLException(sqle);
        }

        PreparedStatement pstmt = conn.prepareStatement(insertString);
        _allStatements.add(pstmt);
        /* rs:                           pstmt:
         * 1 -> COUNTRY                  
         * 2 -> CITY                     1 -> COUNTRY
         * 3 -> ACCENTCITY               2 -> CITY
         * 4 -> REGION                   3 -> REGION
         * 5 -> POPULATION               4 -> POPULATION
         * 6 -> LATITUDE                 5 -> LATITUDE
         * 7 -> LONGITUDE                6 -> LONGITUDE
         */
        rs = Csv.getInstance().read(_csvFileName, null, _csvCharset);
        int rowCount = 0;
        while (rs.next()) {
            if (rs.getFloat(5) != 0) { // If population is not null.
                pstmt.setString(1, rs.getString(1)); // country
                pstmt.setString(2, rs.getString(3)); // city (accentcity in reality)
                pstmt.setString(3, rs.getString(4)); // region
                pstmt.setFloat(4, rs.getFloat(5));   // population
                pstmt.setFloat(5, rs.getFloat(6));   // latitude
                pstmt.setFloat(6, rs.getFloat(7));   // longitude
                pstmt.addBatch();
                rowCount ++;
            }
        }
        int[] rowsUpdated = pstmt.executeBatch();
        for (int i=0; i<rowsUpdated.length; i++) {
            if (rowsUpdated[i] == -2) {
                logger.error("Execution {}: unknown number of rows inserted.", i);
                logger.error("Rolling back ...");
                conn.rollback(savept1);
            } else {
                logger.trace("Successful: execution {}, {} rows updated !", i, rowsUpdated[i]);
            }
        }
        conn.commit();
    }
    finally { // release all open resources to avoid unnecessary memory usage.

.... `

Спасибо!

2 голосов
/ 01 марта 2011

Используйте метод read() класса H2 Csv, итерируйте по ResultSet, вставляя нужные строки по мере их нахождения.

...