什么时候SQLiteOpenHelper onCreate()/ onUpgrade()运行?

laa*_*lto 284 sqlite android sqlexception sqliteopenhelper android-sqlite

我已经在我的桌子上创建了我的桌子SQLiteOpenHelper onCreate()但收到了

SQLiteException: no such table
Run Code Online (Sandbox Code Playgroud)

要么

SQLiteException: no such column
Run Code Online (Sandbox Code Playgroud)

错误.为什么?

注意:

(这是每周数十个类似问题的合并摘要.试图在这里提供一个"规范的"社区维基问题/答案,以便所有这些问题可以引导到一个很好的参考.)

laa*_*lto 346

SQLiteOpenHelper onCreate()onUpgrade()当数据库实际上是打开,例如通过将呼叫回调调用getWritableDatabase().创建数据库帮助程序对象本身时,不会打开数据库.

SQLiteOpenHelper版本数据库文件.版本号是int传递给构造函数的参数.在数据库文件中,版本号存储在PRAGMA user_version.

onCreate()仅在数据库文件不存在且刚刚创建时运行.如果onCreate()成功返回(不抛出异常),则假定使用请求的版本号创建数据库.作为一种暗示,你不应该自己SQLException陷入onCreate()困境.

onUpgrade()仅在数据库文件存在时调用,但存储的版本号低于构造函数中请求的版本号.本onUpgrade()应更新表架构所需的版本.

在代码(onCreate())中更改表模式时,应确保更新数据库.两种主要方法:

  1. 删除旧的数据库文件,以便onCreate()再次运行.在开发时,您通常首选这种方法,您可以控制已安装的版本,并且数据丢失不是问题.删除数据库文件的一些方法:

    • 卸载应用程序.使用应用程序管理器或adb uninstall your.package.nameshell.

    • 清除申请数据.使用应用程序管理器.

  2. 增加数据库版本以便onUpgrade()调用.由于需要更多代码,这稍微复杂一些.

    • 对于数据丢失不是问题的开发时模式升级,您可以使用execSQL("DROP TABLE IF EXISTS <tablename>")in来删除现有表并调用onCreate()以重新创建数据库.

    • 对于已发布的版本,您应该实施数据迁移,onUpgrade()以便用户不会丢失数据.

  • 因此,每次修改架构时,我都需要在SQLiteHelper中对DB VERSION进行硬编码,这样当旧应用程序运行并获取数据库连接并发现它已经过时,然后onUpgrade将被trgii而不是onCreate,这是对? (4认同)
  • @Laalto // onUpgrade()中的数据迁移//你能解释一下吗? (2认同)
  • @bala不在本问题/答案的范围内.如果您有任何疑问,请随时将其发布为问题. (2认同)
  • @Jaskey版本号用于代码,即代码期望运行的模式版本.如果文件较旧(来自以前版本的应用程序),则需要升级. (2认同)
  • 谢谢 !这对我来说很有意义。请验证我是否理解。因此,我们需要执行1.每次更新架构时,都要修改DB_VERSION变量(硬代码)。2.在`onUpdate()`中,检查每个旧版本并进行适当的数据迁移。然后,当用户更新其应用程序(它们具有旧的db文件)时,将触发“ onUpgrade”,如果是新安装用户,则将触发“ onCreate()”。 (2认同)

Aun*_*Aun 96

根据Jaskey的要求,在这里进一步添加缺失点

数据库版本存储在SQLite数据库文件中.

catch是构造函数

SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)
Run Code Online (Sandbox Code Playgroud)

因此,当使用name(第二个参数)调用数据库帮助程序构造函数时,平台会检查数据库是否存在,如果数据库存在,它将从数据库文件头获取版本信息并触发正确的回调

正如旧答案中已经解释的那样,如果名称的数据库不存在,则会触发onCreate.

下面onUpgrade以一个例子说明案例.

比如说,你的第一个版本的应用程序有DatabaseHelper(扩展SQLiteOpenHelper)构造函数传递版本1,然后你提供了一个升级的应用程序,其新的源代码版本传递为2,然后在DatabaseHelper构造时自动,平台onUpgrade通过查看文件已经存在触发,但版本低于您通过的当前版本.

现在假设您正在计划将db版本的应用程序的第三个版本作为3(只有在修改数据库模式时才增加db版本).在这种增量升级中,您必须逐步编写每个版本的升级逻辑,以获得更好的可维护代码

示例伪代码如下:

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  switch(oldVersion) {
    case 1:
       //upgrade logic from version 1 to 2
    case 2:
       //upgrade logic from version 2 to 3
    case 3:
       //upgrade logic from version 3 to 4
       break;
    default:
       throw new IllegalStateException(
                "onUpgrade() with unknown oldVersion " + oldVersion);
  }
}
Run Code Online (Sandbox Code Playgroud)

注意break案例中的缺失语句12.这就是增量升级的意思.

说,如果旧版本2和新版本4,那么逻辑将升级数据库23,然后到4

如果旧版本3和新版本4,它只是运行升级的逻辑34

  • @param用户无法做到这一点.他只能将2升级到最新版本(此处为4). (6认同)
  • 我认为你希望你的 switch(newVersion) 改为 switch(oldVersion) 。您可能还想验证 newVersion 是 4 (而不是 5 或 3;因为您的逻辑假设新版本应该是 4)。事实上,如果旧版本是 2 而新版本是 5,您将遇到情况 4:并从 3 升级到 4(这可能不是预期的行为)。 (2认同)

jee*_*mar 20

onCreate()

  1. 当我们第一次创建DataBase(即数据库不存在)时,onCreate()使用传入的版本创建数据库 SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)

  2. onCreate()方法是创建您定义的表并执行您编写的任何其他代码.但是,只有在应用程序的数据目录(/data/data/your.apps.classpath/databases)中缺少SQLite文件时,才会调用此方法.

  3. 如果您已更改代码并在模拟器中重新启动,则不会调用此方法.如果要onCreate()运行,则需要使用adb删除SQLite数据库文件.

onUpgrade()

  1. SQLiteOpenHelper 应该调用超级构造函数.
  2. onUpgrade()仅当版本整数大于应用程序中运行的当前版本时,才会调用此方法.
  3. 如果要onUpgrade()调用该方法,则需要在代码中增加版本号.


Kus*_*ush 10

可能是我来不及但是我想分享我的简短回答.请检查答案 是否存在同样的问题.它一定会帮到你.没有更深入的规格.

如果您对创建表的语法有信心,那么当您在同一个表中添加新列时可能会发生这种情况...

1)从您的设备卸载并再次运行.

要么

2)设置 - > app - > ClearData

要么

3)更改DATABASE_VERSION"DatabaseHandler"类(如果添加了新列,则会自动升级)

public DatabaseHandler(Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
Run Code Online (Sandbox Code Playgroud)

要么

4)改变DATABASE_NAME你的"DatabaseHandler"类(我遇到了同样的问题.但是我通过改变成功了DATABASE_NAME.)


Jib*_*eeb 5

延长时要记住的要点 SQLiteOpenHelper

  1. super(context, DBName, null, DBversion); - 这应该在构造函数的第一行调用
  2. 覆盖onCreateonUpgrade(如果需要)
  3. onCreate只会在getWritableDatabase()getReadableDatabase()被执行时被调用。这只会DBName在第一步中指定的a不可用时调用一次。您可以添加创建表查询onCreate方法
  4. 每当您想添加新表时,只需更改DBversion并在onUpgrade表中执行查询或简单地卸载然后安装该应用程序。