【问题标题】:Should simultaneously having multiple different SQLite Database Versions be considered harmful?同时拥有多个不同的 SQLite 数据库版本是否应该被认为是有害的?
【发布时间】:2014-04-15 16:36:04
【问题描述】:

我将每个 SQLite 表的代码(包括表的初始构造以及对该表的操作)分解为扩展 SQLiteOpenHelper 的单独类。

为了创建这些表(也就是说,要调用 onCreate() 方法),我必须增加 DATABASE_VERSION(详见my own answer here)。

但是使用这种方法,我最终会为每个类/表设置不同的版本号——我必须将我创建的第二个表的 DATABASE_VERSION 值设置为 2,我必须将第三个表设置为 3,等等。

所以我最终会为同一个 DATABASE(*.db 文件)获得多个不同的版本值。如果它们都是相同的val,则不会调用onUpgrade()方法,因此不会调用onCreate()方法,因此不会创建新表。

这“可以”吗 - 拥有一个同时包含多个不同版本号的数据库?

我知道的唯一其他(合理)选项是将所有数据库代码(覆盖多个表)放入扩展 SQLiteOpenHelper 的单个类中 - 这样做实际上是首选方法吗? IOW,我将 db 代码分成几个类,每个表一个类,是帮助还是阻碍?

更新

所以这是我的非破坏性方式(通过在 DDL 中插入“IF NOT EXISTS”)逐步添加新表,根据 CommonsWare 的建议,只使用一个扩展 SQLiteOpenHelper 的类:

@Override
public void onCreate(SQLiteDatabase db) {
    String CONDITIONALLY_CREATE_VENDORS_TABLE = "CREATE TABLE IF NOT EXISTS " +
            TABLE_VENDORS + "("
            + COLUMN_ID + " INTEGER PRIMARY KEY," + COLUMN_VENDORID
            + " TEXT," + COLUMN_COMPANYNAME + " TEXT" + ")";
    db.execSQL(CONDITIONALLY_CREATE_VENDORS_TABLE);
    // add more tables as needed following the pattern above
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    //db.execSQL("DROP TABLE IF EXISTS " + TABLE_VENDORS); <= Only need to DROP if the table's structure changes; so comment such a line out for the particular table in that case
    onCreate(db);
}

注意:每当我添加一个新表时,我必须“向上”(增加)DATABASE_VERSION 值,以便 onUpgrade()/onCreate()调用。

【问题讨论】:

  • 如果我理解正确,您打算将现有表拆分为两个或多个新建表。这可以在不修改数据库版本的情况下完成。如果您更改数据库版本,则将调用 onUpgrade 方法。这将清除您在任何表中拥有的所有现有数据,这根本不需要。此外,如果您想更改某些 EXISTING 表的表结构,onUpgrade 和 DB 版本可能会有所帮助,但在您的情况下,您只是希望将一个表分成两个或多个新表。
  • 不,我不是在说将一个表重构为 N 个表;我只是在谈论将新表添加到现有数据库中(一次添加一个表到代码中)。

标签: android sqlite oncreate sqliteopenhelper database-versioning


【解决方案1】:

我将每个 SQLite 表的代码(包括表的初始构造以及对该表的操作)分解为扩展 SQLiteOpenHelper 的单独类

出于线程安全以及其他原因,拥有一个您始终使用的SQLiteDatabase 实例非常重要。反过来,这将要求您拥有一个 SQLiteOpenHelper 课程。完全独立的数据库文件例外(每个数据库一个 SQLiteHelper),但通常不需要。

这“可以”吗 - 拥有一个同时包含多个不同版本号的数据库?

这根本不是“好的”。人数最多的获胜。

我知道的唯一其他(合理)选项是将所有数据库代码(覆盖多个表)放入扩展 SQLiteOpenHelper 的单个类中 - 这样做实际上是首选方法吗? IOW,我将 db 代码分成几个类,每个表一个类,是帮助还是阻碍?

将“数据库代码分成几个类,每个表一个”不一定是问题。 的问题是让它们成为SQLiteOpenHelper 的独立子类。

假设您希望这些类不仅可以处理表的创建和升级,还可以处理与表相关的其他 CRUD 操作。有一个专门的课程很好。但是,表创建和升级逻辑需要由单个 SQLiteOpenHelper 类驱动。只需将onCreate()onUpgrade() 放在SQLiteOpenHelper 上,将实际工作委托给每个表类。这样,您就可以组织代码,而无需多个 SQLiteOpenHelper 类。

【讨论】:

  • 我看不出“中奖最高号码”有什么问题。它适用于我到目前为止添加的两个表;第一个版本为 1,第二个版本为 2。我能够在不删除第一个表的情况下将记录添加到第二个表(在“增加”该类中的版本号之后)。如果我只有一个版本号(在扩展 SQLiteOpenHelper 的单个类中),我是否不必在每次添加新表时增加数据库的版本号,这反过来会 DROP(然后重新创建)所有以前的表,从而清除存储在其中的数据?
  • 就线程安全而言,一次只有一个表,因此一次只有一个扩展 SQLiteOpenHelper 的类将处于活动状态。
  • @B.ClayShannon:“每次添加新表时,我是否都必须增加数据库的版本号”——是的。 “这反过来会删除(然后重新创建)所有以前的表,从而清除存储在其中的数据?” -- 仅当您在onUpgrade() 中这样做时。大多数开发人员不会那样做。 “一次只有一张桌子......会处于活动状态” - 我不知道“活动”在这里意味着什么。但是,由于您为数据库 I/O 使用后台线程,因此无论是否“活动”,都会使用 2 个以上的线程。
  • @B.ClayShannon:你真的应该查看传递给onUpgrade() 的版本并根据它做出决定,类似于 Rails 迁移的处理方式。一旦您想向表中添加列以及其他不仅仅是添加新表的更改,您链接到onCreate() 的解决方案将无法在现实世界中长期使用。
  • @B.ClayShannon:除了会丢失你的数据。使用ALTER TABLE 添加列。在紧要关头,您可以将现有表中的数据复制到临时表中,删除并重建真实表,然后使用INSERT INTO ... SELECT FROM ... 将数据从临时表中取回到重建的真实表中。
猜你喜欢
  • 1970-01-01
  • 2015-09-09
  • 2011-12-28
  • 1970-01-01
  • 2011-10-08
  • 1970-01-01
  • 2014-11-24
  • 2010-12-22
  • 2010-11-08
相关资源
最近更新 更多