Путаница: как работает SQLiteOpenHelper onUpgrade()? И вместе с импортом старой резервной копии базы данных?

предположим, что у меня есть таблица базы данных test_table с 2 столбцами и соответствующее создание script в SQLiteOpenHelper:

DB_VERSION = 1:
public void onCreate(SQLiteDatabase db)
{
db.execSql("CREATE table test_table (COL_A, COL_B);
}

Это начальная версия приложения 1, которая публикуется в Play Маркете.

Через некоторое время обновляется приложение и используемая база данных. Я думаю, класс SQLiteOpenHelper должен быть адаптирован следующим образом:

DB_VERSION = 2:
public void onCreate(SQLiteDatabase db)
{
db.execSql("CREATE table test_table (COL_A, COL_B, COL_C)");
}

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
db.execSql("ALTER TABLE test_table ADD Column COL_C");
}

Через некоторое время обновится другое приложение:

DB_VERSION = 3:
public void onCreate(SQLiteDatabase db)
{
db.execSql("CREATE table test_table (COL_A, COL_B, COL_C, COL_D)");
}

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
db.execSql("ALTER TABLE test_table ADD Column COL_D");
}

- > Здесь мне нужен совет. Если пользователь устанавливает приложение 1, у него есть столбцы A и B. Если он затем обновляется до версии 2, onUpgrade запускает и добавляет столбец C. Новые пользователи, которые устанавливают с нуля, получают три столбца с помощью инструкции create. Если пользователь затем обновляется до версии 3, onUpgrade запускается снова и добавляется столбец D. Но ЧТО ЕСЛИ пользователь устанавливает приложение 1, а затем пропускает обновление версии 2 и обновляет версию 3? Тогда он бы пропустил

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)

    {
    db.execSql("ALTER TABLE test_table ADD Column COL_C");
    }

часть и только

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)

    {
    db.execSql("ALTER TABLE test_table ADD Column COL_D");
    }

что приведет к таблице test_table (COL_A, COL_B, COL_D)??

Каков правильный способ обработки обновлений базы данных в прямом приложении, чтобы пользователь не потерял свои данные? Нужно ли проверять все возможные (старые) версии в методе onUpgrade() и выполнять разные инструкции таблиц переменных на основе этой версии?

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

Что произойдет, если пользователь имеет приложение версии 1, экспортирует базу данных, обновляет приложение (новая структура базы данных) и импортирует резервную копию старой версии 1? - > Как будет вести себя SQLiteOpenHelper? - > Каков правильный способ обработки обновлений db вместе с функциями импорта/экспорта?

Ответ 1

Каков правильный способ обработки обновлений базы данных в прямом приложении, чтобы пользователь не потерял свои данные? Нужно ли проверять все возможные (старые) версии в методе onUpgrade() и выполнять разные инструкции таблиц переменных на основе этой версии?

В общем, да.

Обычный подход к этому заключается в том, чтобы сделать пару обновления:

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  if (oldVersion<2) {
    // do upgrade from 1 to 2
  }

  if (oldVersion<3) {
    // do upgrade from 2 to 3, which will also cover 1->3,
    // since you just upgraded 1->2
  }

  // and so on
}

Это примерно соответствует, например, миграции Rails.

Что произойдет, если пользователь имеет приложение версии 1, экспортирует базу данных, обновляет приложение (новая структура базы данных) и импортирует резервную копию старой версии 1? → Как будет вести себя SQLiteOpenHelper?

Если при "копировании всей базы данных" вы буквально означаете полную копию файла базы данных SQLite, тогда, когда SQLiteOpenHelper отправится открывать восстановленную резервную копию, она будет иметь версию старой схемы и будет выполните onUpgrade() как обычно.

Каков правильный способ обработки обновлений db вместе с функциями импорта/экспорта?

Я подозреваю, что ответ: либо сделайте резервную копию, скопировав весь файл, либо также организуйте резервное копирование и восстановление версии схемы, которую вы можете получить, вызвав getVersion() на объект SQLiteDatabase. Это, как говорится, я не рассматривал этот сценарий много, и может быть больше проблем, о которых я не думаю.

Ответ 2

ниже код psuedo показывает улучшенное обновление

@Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        switch(oldVersion) {

        case 2:
                //upgrade logic from version 2 to 3
        case 3:
                //upgrade logic from version 3 to 4
        case 4:
                //upgrade logic from version 4 to 5
                break;
        default:
                throw new IllegalStateException(
                "onUpgrade() with unknown oldVersion" + oldVersion));
        }
    }

Посредством инкрементного обновления я имею в виду - Обратите внимание на отсутствующий оператор break в случаях 2 и 3

скажем, если старая версия равна 2, а новая версия - 4, тогда логика обновит базу данных с 2 до 3, а затем до 4

если старая версия - 3, а новая версия - 4, она просто запустит логику обновления от 3 до 4

продолжать добавлять новые случаи для каждого обновления новой версии базы данных, которые будут делать дополнительные изменения

Ответ 3

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

CREATE TABLE new_test_table (COL_A, COL_B, COL_C,COL_D);

скопировать данные из старой таблицы в новую

INSERT INTO new_test_table SELECT * FROM test_table;

удалить старую таблицу DROP TABLE test_table;

и переименуйте новую таблицу

ALTER TABLE new_test_table RENAME TO test_table;

так короче

public void onUpgrade(SQLiteDatabase db,int OldVersion,int NewVersion){
  db.execSQL("CREATE TABLE new_test_table (COL_A, COL_B, COL_C,COL_D);"+
             "INSERT INTO new_test_table SELECT * FROM test_table;"+
             "DROP TABLE test_table;"+
             "ALTER TABLE new_test_table RENAME TO test_table;");"
    }

таким образом вам не нужно беспокоиться о dataloss или дополнительных изменениях

Ответ 4

Android-Database-Upgrade-Tutorial показывает подробное руководство по тому, как вы обрабатываете повышение градации вашей схемы базы данных приложения при выпуске новых версий приложений.

Учебник состоит из приложения, имеющего 4 версии, каждая версия содержит различное количество столбцов, Различные версии приложения

Это разные сценарии, с которыми можно столкнуться Различные сценарии