困惑:SQLiteOpenHelper onUpgrade()如何表现?和导入旧的数据库备份一起?

时间:2013-01-19 22:04:36

标签: android import export sqliteopenhelper

让我们假设我在SQLiteOpenHelper中有一个包含2列的数据库表test_table和相应的创建脚本:

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列。 如果用户随后更新到版本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语句?

我问,因为在我的应用程序中,用户可以导出和导入数据,这只不过是导出:复制整个数据库并导入:用备份副本数据库替换app数据库。

如果用户拥有应用版本1,导出数据库,升级应用(新数据库结构)并导入旧版本1备份,会发生什么? - > SQLiteOpenHelper将如何表现? - >处理数据库升级和导入/导出功能的正确方法是什么?

4 个答案:

答案 0 :(得分:33)

  

处理实时应用的数据库升级的正确方法是什么,因此用户不会丢失数据?您是否必须在onUpgrade()方法中检查所有可能的(旧)版本,并根据该版本执行不同的alter table语句?

总的来说,是的。

一种常见的方法是进行成对升级:

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备份,会发生什么? - &GT; SQLiteOpenHelper将如何表现?

如果通过“复制整个数据库”,你的字面意思是SQLite数据库文件的完整文件副本,那么当SQLiteOpenHelper打开还原的备份时,数据库将具有旧的模式版本并将照常进行onUpgrade()

  

使用导入/导出功能处理数据库升级的正确方法是什么?

我怀疑答案是:通过复制整个文件来进行备份,或者还安排备份和恢复架构版本,您可以通过调用getVersion()对象上的SQLiteDatabase来获取该版本。话虽如此,我还没有多少处理这个场景,可能还有更多我没想到的问题。

答案 1 :(得分: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的升级逻辑

不断为每个新的数据库版本升级添加新案例,以进行增量更改

答案 2 :(得分: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;");"
    }

这样您就不必担心数据删除或增量更改

答案 3 :(得分:0)

我认为回答这个问题为时已晚,但可能有助于其他人。

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


      public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
        {
             switch (oldVersion) {
        case 1:                     db.execSql("ALTER TABLE test_table ADD Column COL_C");
                                    db.execSql("ALTER TABLE test_table ADD Column COL_D");
                                    db.execSql("ALTER TABLE test_table ADD Column COL_E");
                            break;
        case 2:                     db.execSql("ALTER TABLE test_table ADD Column COL_D");
                                    db.execSql("ALTER TABLE test_table ADD Column COL_E");
                            break;
        case 3:                     db.execSql("ALTER TABLE test_table ADD Column COL_E");

                            break;

and so on...
}

如果用户第一次安装应用,他将从 onCreate

获取所有列

如果旧版本的数据库2,则案例2添加C和D列。

如果旧版本的数据库3,则案例3仅添加列E

通过这种方式,数据库版本没有混淆。