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

Ton*_*oni 27 import android export sqliteopenhelper

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

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

这是最初的应用版本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");
}
Run Code Online (Sandbox Code Playgroud)

一段时间后,另一个应用更新:

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");
}
Run Code Online (Sandbox Code Playgroud)

- >这是我需要建议的地方.如果用户安装了应用版本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");
    }
Run Code Online (Sandbox Code Playgroud)

部分和唯一

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

    {
    db.execSql("ALTER TABLE test_table ADD Column COL_D");
    }
Run Code Online (Sandbox Code Playgroud)

会被调用,这会导致表test_table(COL_A,COL_B,COL_D)??

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

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

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

Com*_*are 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
}
Run Code Online (Sandbox Code Playgroud)

例如,这大致等同于Rails迁移.

如果用户具有应用版本1,导出数据库,升级应用程序(新数据库结构)并导入旧版本1备份会发生什么? - > SQLiteOpenHelper将如何表现?

如果通过"复制整个数据库",您实际上意味着SQLite数据库文件的完整文件副本,那么当SQLiteOpenHelper打开还原的备份时,数据库将具有旧的模式版本并将onUpgrade()正常进行.

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

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


Aun*_*Aun 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));
        }
    }
Run Code Online (Sandbox Code Playgroud)

通过增量升级我的意思是 - 注意案例2和3中缺少的break语句

如果旧版本为2且新版本为4,则逻辑将数据库从2升级到3然后再升级到4

如果旧版本为3,新版本为4,则只运行3到4的升级逻辑

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

  • 如果安装的版本是2,那么onUpgrade将被oldVersion命中为2,这意味着现在将切换案例执行案例2 +案例3 +案例4,因为在所有旧案例中缺少break语句.请注意,在旧版本的情况下,break语句不应该存在,因为我们正在进行incteamental升级 (3认同)
  • 即使这两个答案是正确的(您和您的正确答案),这也更易于实现,没有重复的代码(我的意思是查询),而且更简洁。可能会因为缺少中断而感到困惑,但是,快点,这是使用switch的一种方式,所以...总之,我喜欢您的回答:) (2认同)