转载请标明出处: http://blog.csdn.net/xx326664162/article/details/50311717 文章出自:薛瑄的博客
你也可以查看我的其他同类文章,也会让你有一定的收货!
Android 中SQLiteOpenHelper 的一个抽象函数
onUpgrade(SQLiteDatabase db,int oldVersion ,int newVersion)
数据库版本不断地迭代升级,根据oldVersion进行一些数据库方面的操作
优点:
1. 因为当前版本已经确定,如果使用newVersion版本进行比较没有意义,完全可以硬编码。所以使用oldVersion与指定数据库版本比较,更利于针对不同数据库版本的进行升级操作
迭代逐级升级,主要是考虑到夸版本升级,比如有的用户一直不升级版本,数据库版本号一直是1,而客户端最新版本其实对应的数据库版本已经是3了,那么我中途可能对数据库做了很多修改,可以迭代升级,方便代码理解和维护。
我所使用的方法:
Sqlite如何修改表结构字段类型
保留原来数据库数据
http://www.cnblogs.com/wang340/archive/2013/05/06/3063135.html
http://m.blog.csdn.net/article/details?id=50260401
http://87426628.blog.163.com/blog/static/6069361820131069485844/
这三篇博客思路:
将原表A改名为临时表B
创建新表C(名称与原表A一样)
导入数据到新表C
删除临时表B
有个图书管理相关的 App,有一张图书表 —— Book,其表结构如下
字段名 | 类型 | 说明 |
---|---|---|
id | INTEGER | 主键 |
name | TEXT | 书名 |
author | TEXT | 作者 |
price | INTEGER | 价格 |
pages | INTEGER | 页数 |
第一版的 App,其 DBHelper 这么写
public class BookStoreDbHelper extends SQLiteOpenHelper {
private static final String DB_NAME = "BookStore.db";
private static final int VERSION = 1;
private static final String CREATE_TBL_BOOK = "CREATE TABLE Book ("
+ "id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "name TEXT, "
+ "author TEXT, "
+ "prices INTEGER, "
+ "pages INTEGER"
+ ")";
public BookStoreDbHelper(Context context) {
this(context, null, null, 0);
}
private BookStoreDbHelper(Context context, String name, CursorFactory factory,
int version) {
super(context, DB_NAME, null, VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_TBL_BOOK);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
几个星期之后,第二版的需求来了,需要增加一个书籍分类表 —— Category,其表结构如下:
字段名 | 类型 | 说明 |
---|---|---|
id | INTEGER | 主键 |
category_name | TEXT | 分类名称 |
category_code | INTEGER | 分类代码 |
这个时候,就需要对数据库进行升级,增加一张表。这时候一个问题就来了:
如何在不影响旧版本 App 稳定性的情况下,对数据库进行升级?
先来看看代码实现,等下再细说为什么这么做。
代码实现如下
private static final int VERSION = 2; // 版本号加 1
// Categroy 建表语句
private static final String CREATE_TBL_CATEGORY = "CREATE TABLE Category ("
+ "id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "category_name TEXT, "
+ "category_code INTEGER"
+ ")";
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_TBL_CATEGORY)
db.execSQL(CREATE_TBL_BOOK); // 建立新表
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
case 1:
db.execSQL(CREATE_TBL_CATEGORY) // 建立新表
default:
break;
}
}
现在来说说为什么这么写。
注意到一点,这是第二版的 App,那么就会有两种用户:
第三版的 App 又提出来一个新需求:要给 Book 表和 Category 表建立关联,要在 Book 表中添加一个 category_id 字段,代码如下
private static final int VERSION = 3; // 版本号加 1,现在是 3
// Book 表
private static final String CREATE_TBL_BOOK = "CREATE TABLE Book ("
+ "id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "name TEXT, "
+ "author TEXT, "
+ "prices INTEGER, "
+ "pages INTEGER, "
+ "category_id INTEGER" // 增加字段
+ ")";
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_TBL_CATEGORY)
db.execSQL(CREATE_TBL_BOOK); // 建立新表
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
case 1:
db.execSQL(CREATE_TBL_CATEGORY) // 建立新表
case 2:
db.execSQL("ALTER TABLE Book ADD COLUMN category_id INTEGER"); // 增加字段
default:
break;
}
}
注意:
OnUpgrade() 方法中的 switch 语句是没有 break 的,会一直执行到语句结束。为什么要这么写想想就明白了。比如用户手上的版本是 1,新版 App 的版本是 5,那么就会有 4 个版本的数据库升级,switch() 自然不能中途 break,必须执行这 4 个版本的数据库升级语句。
优点:
每次更新数据库的时候只需要在onUpgrade方法的末尾加一段从上个版本升级到新版本的代码,易于理解和维护
缺点:
当版本变多之后,多次迭代升级可能需要花费不少时间,增加用户等待时间
表2.1
版本 | 字段1 | 字段2 | 字段3 | 字段4 | 字段5 |
---|---|---|---|---|---|
1 | ID | name | password | ||
2 | ID | name | password | address | |
3 | ID | name | password | address | subject |
4 | ID | name | password | ||
ID | subject |
发现数据库3存在冗余,需要拆分数据库为4,此时只需要改变对应旧版本为3的升级操作,实现迭代升级
针对当前newVersion版本号,对每个版本的数据库进行升级操作
数据库版本1 | 数据库版本2 | 数据库版本3 | newVersion |
---|---|---|---|
1->4 | 2->4 | 3->4 | 4 |
1->5 | 2->5 | 3->5 | 5 |
以数据库版本1、2、3为例,可以看出每次有新数据库版本时,为了保留原来数据库中的数据,这三个版本都需要进行相应的修改(红色部分)。(上面蓝色的那句话就是这种情况)
增加字段
删除字段、或增删新表
所以这种跳跃升级不建议使用
优点:
优点:跨版本升级效率高,可以保证每个版本的用户都可以在消耗最少的时间升级到最新的数据库而无需做无用的数据多次转存
缺点:
代码维护量将越来越大,强迫开发者记忆所有版本数据库的完整结构,且每次升级时onUpgrade方法都必须全部重写
参考:
http://www.jianshu.com/p/65a025637d40
http://www.cnblogs.com/liqw/p/4264925.html
http://flyingcat2013.blog.51cto.com/7061638/1537074
关注我的公众号,轻松了解和学习更多技术