27

2 つの列を持つデータベース テーブル test_table と、SQLiteOpenHelper に対応する作成スクリプトがあるとします。

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

これは、Play ストアで公開されている最初のアプリ バージョン 1 です。

しばらくすると、アプリと使用されているデータベースが更新されます。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 つの列を取得します。その後、ユーザーがバージョン 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() メソッドで考えられるすべての (古い) バージョンをチェックし、そのバージョンに基づいて別の alter table ステートメントを実行する必要がありますか?

私のアプリでは、ユーザーはデータをエクスポートおよびインポートする可能性があるため、これはエクスポートにすぎません: データベース全体をコピーし、インポート: アプリ データベースをバックアップ コピー データベースに置き換えます。

ユーザーがアプリ バージョン 1 を持っていて、データベースをエクスポートし、アプリ (新しいデータベース構造) をアップグレードして、古いバージョン 1 のバックアップをインポートするとどうなりますか? --> SQLiteOpenHelper はどのように動作しますか? --> インポート/エクスポート機能とともにデータベースのアップグレードを処理する正しい方法は何ですか?

4

4 に答える 4

34

ユーザーが自分のデータを失わないように、ライブ アプリのデータベース アップグレードを処理する正しい方法は何ですか? 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()、通常どおり処理されます。

インポート/エクスポート機能とともにデータベースのアップグレードを処理する正しい方法は何ですか?

答えは、ファイル全体をコピーしてバックアップを作成するかgetVersion()、オブジェクトを呼び出して取得できるスキーマ バージョンのバックアップと復元を手配することだと思いSQLiteDatabaseます。そうは言っても、私はこのシナリオをあまり扱っていません。私が考えていない問題が他にもあるかもしれません。

于 2013-01-19T22:36:39.413 に答える
19

以下の疑似コードは、段階的アップグレードを示しています

@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));
        }
    }

インクリメンタル アップグレードとは、ケース 2 と 3 で break ステートメントが欠落していることに注意してください。

たとえば、古いバージョンが 2 で新しいバージョンが 4 の場合、ロジックはデータベースを 2 から 3 にアップグレードしてから 4 にアップグレードします。

古いバージョンが 3 で新しいバージョンが 4 の場合、3 から 4 へのアップグレード ロジックが実行されます。

増分変更を行う新しいデータベース バージョンのアップグレードごとに新しいケースを追加し続ける

于 2014-11-14T12:02:32.987 に答える
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;");"
    }

そうすれば、データの損失や増分変更について心配する必要がなくなります

于 2015-11-02T05:56:25.933 に答える