App版本更新时对SQLite数据库升级或者降级遇到的问题
SQLite是Android内置的一个很小的关系型数据库。SQLiteOpenHelper是一个用来辅助管理数据库创建和版本升级问题的抽象类。我们可以继承这个抽象类,实现它的一些方法来对数据库进行自定义操作。下面两个方法必须重写:
- public void onCreate(SQLiteDatabase db)
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
另外SQLiteOpenHelper子类在构造实例时必须指定当前数据库的名称(name)、版本号(version)。而这里名称就决定了数据库存储时的文件名称,而这里的版本号与App在AndroidMainfest.xml定义的versionCode没有绝对关联。也就是在App更新时如果数据库的数据结构没有发生变化那么数据库的版本号则不用增加。
onCreate:调用时机是用户首次安装应用后启动,或是清除App数据库文件后启动。这时可以在这个函数中完成初始的数据表的创建。
onUpgrade:调用时机是用户在做应用更新,覆盖安装后启动,如果新版本中数据库版本号要比旧版本中的数据库版本号高则会调用。这时可以在这个函数完成数据库版本升级带来的旧版本的兼容问题,以及数据迁移问题。
还有一个一般情况下不需要重写,但在应用出现逆向降级(如应用由版本号4降级安装版本号为3的包)时必须重写的方法onDowngrade,如果应用降级覆盖安装时没有重写该方法则会崩溃。
在数据库版本升级时, 我们可能会遇到这样一些情况:
- 需要扩展一个表的字段
- 删除掉原来表上某个冗余的字段
- 新建一个表
而处理上面这些问题都要在不损害旧数据库历史数据的前提下完成。这里我们假设用户手机上之前安装的是数据库版本为1的包,升级安装的是数据库版本号为2的包。这时我们要在数据库版本为2的包在去处理这些升级逻辑。
首先是扩展一个表的字段在onUpgrade中的实现为:
MyDBHelper.java
1
2
3
4
5
6
7
|
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//旧数据库版本为1,才为表pedant添加一个student_name字段
if(oldVersion < 2) {
db.execSQL("ALTER TABLE pedant ADD COLUMN student_name text");
}
}
|
SQLite对ALTER TABLE的支持是有限的,你可以在一个存在表上添加一个字段到末尾,或者是改变表的名称。但如果你想做更复杂的操作,比如删除一个表已有的字段,就要重新创建这个表并完成数据迁移,而不能使用DROP COLUMN这样方便的命令了。详见SQLite Frequently Questions
比如表pedant原来有三个字段a、b、c,现在想删除c字段,那么在onUpgrade中写法如下:
MyDBHelper.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//旧数据库版本为1,删除表pedant的c字段
if(oldVersion < 2) {
db.beginTransaction();
try {
db.execSQL("CREATE TEMPORARY TABLE pe_backup (a, b);");
db.execSQL("INSERT INTO pe_backup SELECT a, b FROM pedant;");
db.execSQL("DROP TABLE pedant;");
db.execSQL("CREATE TABLE pedant(a text, b text);");
db.execSQL("INSERT INTO pedant SELECT a, b FROM pe_backup;");
db.execSQL("DROP TABLE pe_backup;");
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
}
|
这样就既完成了对c字段的删除也保留了原来表上的数据。
最后一种情况最简单直接执行CREATE语句就要可以了。
MyDBHelper.java
1
2
3
4
5
6
7
|
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//旧数据库版本为1,创建新表newtb
if(oldVersion < 2) {
db.execSQL("CREATE TABLE newtb(a text, b text);");
}
}
|
数据库在做升级时我们能明确地知道当前我们要对各旧表进行什么样的操作来兼容新版本。但如果在数据库降级时,情况就不一样了,针对我们开发新版本2时, 我们不能明确地知道以后的新版本比如版本3、4的数据库结构走向是怎样的。比如以后用户从版本3回退到我们正在开发的版本2,由于我们开发当时不能预知版本3的表结构,不知版本3的数据表能否兼容到版本2(假如版本3升级时删除了一个版本2一直在用的表字段,这时回退数据结构可能就不兼容了),那么我们在开发版本2时最稳妥的做法是重写onDowngrade时把所有当前版本将用到的表全部重建,即降级时扔掉以前全部的数据。
MyDBHelper.java
1
2
3
4
5
6
7
8
9
10
|
// 因为我们无法预知未来版本的表结构,向下兼容时最稳妥的方法就是将该版本自己需要的表重构一次
@Override
public void onDowngrade (SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS t1;");
db.execSQL("DROP TABLE IF EXISTS t2;");
db.execSQL("DROP TABLE IF EXISTS t3;");
db.execSQL("DROP TABLE IF EXISTS t4;");
....
onCreate(db); // 建表
}
|
欢迎转载,请注明出处链接!!!
App版本更新时对SQLite数据库升级或者降级遇到的问题的更多相关文章
- Android版本更新时对SQLite数据库升级或者降级遇到的问题
SQLite是Android内置的一个很小的关系型数据库.SQLiteOpenHelper是一个用来辅助管理数据库创建和版本升级问题的抽象类.我们可以继承这个抽象类,实现它的一些方法来对数据库进行自定 ...
- Android SQLiteOpenHelper Sqlite数据库升级onUpgrade
Android Sqlite数据库升级,在Android APP开发之中,非常常见: 在确定原来的数据库版本号之后,在原来数据库版本号+1,就会执行onUpgrade方法,进行数据库升级操作: 在on ...
- Android SQLite数据库升级,怎么做(事物更改)
SQLiteOpenHelper // 如果数据库文件不存在,只有onCreate()被调用(该方法在创建数据库时被调用一次) public abstract void onCreate(SQLite ...
- Android数据库升级、降级、创建(onCreate() onUpgrade() onDowngrade())[4]
数据库版本升级对软件的管理操作. 我们手机经常会收到xxx软件升级什么的提醒,你的软件版本更新,同时你的数据库对应的版本也要相应的更新. 数据库版本更新需要主要的问题: 软件的1.0版本升级到1.1版 ...
- Android笔记——数据库升级与降级
一.概述 SQLite是Android内置的一个很小的关系型数据库.SQLiteOpenHelper是一个用来辅助管理数据库创建和版本升级问题的抽象类.我们可以继承这个抽象类,实现它的一些方法来对数据 ...
- Android之数据库升级onUpgrade降级onDowngrade
借用API文档解释: public abstract void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 当数据库需要升 ...
- Android数据库升级、降级、创建(onCreate() onUpgrade() onDowngrade())的注意点
以下内容可以作为面试官在面试的时候的问题,感觉比较好,是比较常用的知识点,可以用来考察基础是否扎实. 也可以程序猿学习.开发中的注意点.因为稍微不注意,就有可能导致数据库不能用. DBAdapter. ...
- Android之sqlite数据库版本升级和降级的处理(onUpgrade和onDowngrade)
一.SQLite升级和降级需要考虑的细节 ① SQLite升级: v3.0数据库版本 [onUpgrade 情况:n-1,onCreate 情况:1] ...
- Android中SQLite数据库小计
2016-03-16 Android数据库支持 本文节选并翻译<Enterprise Android - Programing Android Database Applications for ...
随机推荐
- Java基础知识强化49:10个实用的但偏执的Java编程技术
1. 将String字符串放在最前面 为了防止偶发性的NullPointerException 异常,我们通常将String放置在equals()函数的左边来实现字符串比较,如下代码: // Bad ...
- 将EXCEL中的列拼接成SQL insert插入语句
工作中经常需要将EXCEL文件中的数据导入到各种数据库,但是对于不熟悉数据库的人来说,如果直接使用命令执行导入,这无疑是一个难题,也是一个风险.这里我们直接在EXCEL文件中拼接成标准的SQL ins ...
- linux伪文件与proc文件
linux/unix系统的文件类型大致可分为三类:普通文件.目录文件和伪文件.常见的伪文件分别是特殊文件.命名管道及proc文件. 伪文件不是用来存储数据的,因此这些文件不占用磁盘空间,尽管这些文件确 ...
- jsp DAO设计模式
DAO(Data Access Objects)设计模式是属于J2EE体系架构中的数据层的操作. 一.为什么要用DAO? 比较在JSP页面中使用JDBC来连接数据库,这样导致了JSP页面中包含了大量的 ...
- (转)ASP.NET 伪静态
1.伪静态:http://www.cnblogs.com/Default.html 目的就是为了赢得更多的收入,至于真否,待SEOer 解答,正如文字所说,伪静态就是假的静态. 2.准备工作:下载Ur ...
- plsql编程中游标的使用
游标(Cursor):用来查询数据库,获取记录集合(结果集)的指针,可以让开发者一次访问一行结果集,在每条结果集上作操作. oracle中显示使用游标一般要包含以下5个步骤: 声明一些变量以便存储从游 ...
- 华为 oj 表示数字(代码有参考)理解算法设计
虽然是初级题目,但是 也不是太容易就做出来的 还是用c++ 好些 因为c++ string 是可以存储到缓冲区的, 字符串长度可以变化 参考了某神的代码 和我的思路一样 ,就拿来主义了,挺经典的一道面 ...
- effective_c++条款20,用pass-by-reference-to-const替换pass-by-value
pass-by-value void f(A a); 1)导致复制是浪费资源 2)多态是导致对象切割 所以我们使用 void f(const A& a) 上面的话针对class,不针对基本类型 ...
- MFC 点击改变文本 加法计时器 伸缩窗体
1.添加所需控件,设置ID:labNum1,txtNum1.txtNum2.txtNum3.btnAdd,并将labNum1的属性Notify->true(控件在被单击或双击时可以发送消息) 2 ...
- ubuntu soft install
1.Mysql 安装就三个命令 mysql服务端 sudo apt-get install mysql-server mysql客户端 sudo apt-get install mysql-clien ...