Подтвердить что ты не робот

База данных Android SQLite, таблица падения WHY и воссоздание при обновлении

В учебниках я следую и много других мест, я вижу это, onUpgrade → drop table if exists, а затем воссоздать таблицу.

Какова цель этого?

private static class DbHelper extends SQLiteOpenHelper{

    public DbHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE " + DATABASE_TABLE + " (" +
                KEY_ROWID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                KEY_NAME + " TEXT NOT NULL, " +
                KEY_HOTNESS + " TEXT NOT NULL);"
        );  
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
        onCreate(db);
    }       
}
4b9b3361

Ответ 1

Я согласен, что при обновлении вы должны добавлять столбцы или добавлять таблицы в свою базу данных. Большинство примеров onupgrade фактически сосут, потому что почему я удаляю все эти данные, а затем воссоздавая таблицу? Я нашел эту запись в блоге. Я называю это методом инкрементного обновления Adams. Он также обрабатывает ситуации, когда пользователи могут не обновлять ваше приложение с каждой версией.

Вот хороший блог на sqlite onupgrade, который не делает drop table.

Ответ 2

Ну, самый распространенный метод в приложениях для Android - "переустанавливать" пользователя, когда происходит обновление базы данных. И учитывая, что любая локальная база данных должна отражать только то, что находится на серверном приложении, гораздо проще просто отбросить базу данных, воссоздать ее и повторно заполнить с сервера, чем тщательно планировать миграции из одной версии в другую.

Это, конечно, не подход лучший, но это проще.

Чтобы сделать пример того, как он будет реализовывать перенос (изменение старой версии базы данных на более новую)

Давайте скажем, что в вашем классе DbHelper вы определяете, что ваша база данных является версией 1, в более поздней версии вашего приложения (версия 2) вам нужно еще несколько столбцов в одной из ваших таблиц.

Итак, вам нужно обновить таблицу и добавить столбцы через ALTER TABLE {tableName} ADD COLUMN COLNew {type};

Отметьте эту ссылку для этого → Вставьте новый столбец в таблицу в sqlite?

чтобы ваш метод onUpgrade() должен был отразить это изменение, добавив:

 @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    switch(oldVersion){
        case 1:
            db.execSQL("ALTER TABLE " + DATABASE_TABLE + " ADD COLUMN " + NEW_COLUMN_NAME + TYPE);
    }
}  

Ответ 3

В зависимости от типа подхода, который вы хотите создать, и насколько важны ваши данные, какая сложность таблицы. Пример. Если ваше приложение было обновлено довольно много раз, а структура таблицы имеет достаточно много изменений, тогда лучше отбросить таблицу и заново создать ее, вместо того, чтобы писать код для изменения структуры для каждой версии db, в этом подходе вы вам нужно будет сделать резервную копию любых данных, которые у вас есть на стороне сервера, чтобы все оставалось в порядке.

Из моего опыта: воссоздание лучше, если вы можете судить о том, что в дальнейшем могут быть изменения, иначе он становится довольно сложным

Ответ 4

Это чистый старт. Метод onCreate имеет действующую в настоящий момент структуру базы данных. Пользователи, которые устанавливают приложение, будут выполнять этот метод. Для пользователей, которые обновляют, будет запущен метод onUpgrade, а DROP TABLE IF EXIST - это чистый старт - на всякий случай, если структура старой и новой таблицы отличается - отбросьте ее, а затем заново создайте в методе onCreate. Надеюсь это поможет!:)

Ответ 5

если вы хотите сохранить данные таблицы, вы можете сбросить его в CSV файлы, а затем вставить их обратно после создания таблиц. (нет необходимости сбрасывать данные на сервер) здесь приведен пример кода для сброса данных. вы можете установить имя файла как имя таблицы. курсор создается из оператора getAll

public boolean createCsvSaveToFile(Cursor cursor, String fileName) throws IOException {
    String csv = "";
    int colunmCount = cursor.getColumnCount();
    /* check if extarnal drive is readerble */
    if (!isExternalStorageWritable()) {
        fileError = "can not save to external storage";
        fileinfo = "Please mount your SD card";
        return false;
    } else {
        /* create the CSV */
        for (int i = 0; i < colunmCount; i++) {
            csv += QUOTES + cursor.getColumnName(i).toString() + QUOTES + INNER_DELIMITER;
        }
        csv = csv.replaceAll(",$", "");
        csv += LINE_END;
        if (cursor.moveToFirst()) {
            do {
                for (int i = 0; i < colunmCount; i++) {//GET COLUNM values
                    csv += QUOTES + cursor.getString(i) + QUOTES + INNER_DELIMITER;
                }
                csv = csv.replaceAll(",$", "");
                csv += LINE_END;
            } while (cursor.moveToNext());
        }
        /* save file */
        File file = getDataDir(fileName);
        FileOutputStream out = new FileOutputStream(file);
        out.write(csv.getBytes());
        out.flush();
        out.close();
        return true;
    }
}

здесь приведен пример кода для вставки данных. если имя файла CSV совпадает с именем таблицы

private void readFromFile(SQLiteDatabase database, File file) {
    boolean hasColunms = false;
    String tableName = file.getName().replaceAll(".csv$", "");
    String sql;
    String colunmNames = "";
    String colunmValues;
    try {
        BufferedReader br = new BufferedReader(new FileReader(file));
        String line;
        while ((line = br.readLine()) != null) {
            if (!hasColunms ) {
                /* get column names */
                line = line.replaceAll("\"", "");
                colunmNames = line;
                hasColunms = true;
            } else {
                line = line.replaceAll("\"", "'");
                colunmValues = line;
                sql = "INSERT INTO " + tableName + " (" + colunmNames + ") VALUES (" + colunmValues + ")";
                database.execSQL(sql);
            }
        }
        br.close();
    } catch (IOException e) {
        database.close();
        /* You may need to add proper error handling here
    }

для прокрутки многих файлов csv можно использовать следующий код

public boolean csvTodatabase(SQLiteDatabase database) {
    FileStuff f = new FileStuff();
    File time;
    /* check if extarnal drive is readerble */
    if (!f.isExternalStorageReadable()) {
        f.fileError = "can not read external storage";
        f.fileinfo = "Please remount your SD card";
        return false;
    } else {
        /* get all files from extarnal drive data */
        ArrayList<File> files = new ArrayList<File>();
        File directory = new File(FileStuff.DATA_DIRECTORY);
        if (!directory.exists()) {
            return false;
        }
        File[] fList = directory.listFiles();
        for (File file : fList) {
            if (file.isFile()) {
                files.add(file);
            }
        }  
        for (File csvfile : files) {
            readFromFile(database, csvfile);
        }
        return true;
    }
}

ПРИМЕЧАНИЕ: readFromFile (база данных, csvfile); является предыдущей функцией