【问题标题】:Android database versioningAndroid 数据库版本控制
【发布时间】:2011-08-29 08:02:02
【问题描述】:

我希望在每次更新应用程序时清除我的应用程序的 sqlite 数据库。 为此,我在 SQLiteDatabase 的“onUpgrade”函数中对所有表进行了删除表查询。

我遇到了两个问题: - 在我的应用程序第一次启动时,我没有做任何特别的事情。 - 在第二次启动时,我添加了一个“setVersion(2)”行。它调用了 onUpgrade 方法,但日志很奇怪:

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
    Log.d("GDB", "onUpgrade "+oldVersion+" -> "+newVersion);
}
----------------------------------------------------------
DEBUG/GDB(5928): onUpgrade 2 -> 1

所以当我做一个 setVersion() 时,这两个版本似乎被切换了.....

我的第二个问题是我第三次启动我的应用程序,没有更改代码(所以 setVersion(2) 已经在这里),再次调用 onUpgrade 方法!我是否错过了将版本明确设置为 2 的内容?

【问题讨论】:

  • 查看定义数据库版本号的代码会很有帮助。您会发布数据库适配器的相关部分吗?
  • 正如我所说的,只是一个 setVersion(2)
  • 这是查看更多适配器的有用之处。我认为你做错了,通过覆盖初始数据库版本而不是当前版本:似乎 SQLite 认为最初创建的版本是 2,但实际上并非如此。
  • 什么是适配器? SQLiteOpenHelper?
  • 是的,加上构造和使用它的代码。

标签: android sqlite versioning upgrade


【解决方案1】:

我认为您不应该直接使用 setVersion 方法在代码中设置数据库的版本。相反,您应该将架构版本传递给 SQLiteOpenHelper 的构造函数(或者至少是扩展它的类)。然后,您的 onUpgrade 方法应包含条件语句,以根据用户从哪个版本升级来决定运行什么。这些条件应形成级联,以便来自低版本的按顺序应用所有数据库更新,以使用户达到当前级别。 因此,当您想要更改架构时,您可以向 onUpgrade 添加一个新条件,并将架构版本向上传递给您的构造函数。

OpenHelper 中的构造函数如下所示:

public TiftHelper(Context context) {
    super(context, DATABASE_NAME, null, SCHEMA_VERSION);
}

那么 onUpgrade 看起来像这样:

@Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.d(TAG, "on upgrade called. Old version:" + oldVersion
                + ". New version:" + newVersion);

        if (oldVersion == 19) {
            db.execSQL("create table challenges_temp as select * from challenges;");
            db.execSQL("drop table challenges;");
            db.execSQL(create_challenges);
            db.execSQL("insert into challenges (_id, name, is_predef, status) select _id, name, is_predef, 'IN_PROGRESS' from challenges_temp");
            db.execSQL("drop table challenges_temp;");
        }
        if (oldVersion <= 20) {
            // adding the status column to the challenges table
            db.execSQL("create table challenges_temp as select * from challenges;");
            db.execSQL("drop table challenges;");
            db.execSQL(create_challenges);
            db.execSQL("insert into challenges (_id, name, is_predef, status) select _id, name, is_predef, 'IN_PROGRESS' from challenges_temp");
            db.execSQL("drop table challenges_temp;");
        }

等等

这对我来说很好。

【讨论】:

  • 谢谢,它通过设置 SCHEMA_VERSION 而不是 setVersion() ;)
最近更新 更多