Android SQLite数据库版本升级原理解析

标签: android sqlite 数据库 | 发表时间:2015-02-02 13:12 | 作者:dyllove98
出处:http://blog.csdn.net

Android使用SQLite数据库保存数据,那数据库版本升级是怎么回事呢,这里说一下。

一、软件v1.0

安装v1.0,假设v1.0版本只有一个account表,这时走继承SQLiteOpenHelper的onCreate,不走onUpgrade。

1、v1.0(直接安装v1.0)

二、软件v2.0

有2种安装软件情况:

1、v1.0   -->  v2.0              不走onCreate,走onUpgrade

2、v2.0(直接安装v2.0)          走onCreate,不走onUpgrade

v1.0版本只有一个account表,软件版本升级到v2.0了,但是v2.0数据库需要新增一个member表,那怎么办呢?这里有2种情况了:一种是安装了v1.0升级到v2.0,这时不会走继承SQLiteOpenHelper的onCreate,而是直接走onUpgrade,这时就要在onUpgrade添加member表的代码了,在onCreate加了也没用,因为这种情况都不走onCreate。。另一种情况就是用户从来没有安装过这个软件,直接安装v2.0,这时走继承SQLiteOpenHelper的onCreate,不走onUpgrade,所以要在onCreate添加member表的代码。这怎么办呢?这就要合理升级数据库版本了。

三、软件v3.0

假设v3.0又新增一个news表,这里有三种情况:

1、v1.0   -->  v3.0              不走onCreate,走onUpgrade

2、v2.0   -->  v3.0              不走onCreate,走onUpgrade

3、v3.0(直接安装v3.0)          走onCreate,不走onUpgrade

那数据库添加表语句在那里写呢?数据库有一个版本号用DATABASE_VERSION表示

其实想一下,就知道不是onCreate写就是onUpgrade写,就是要兼容各种情况下安装app,都能把数据库表添加进去就好了。这里很巧妙:

1、v1.0     DATABASE_VERSION=1000    onCreate      --添加--  account

2、v2.0     DATABASE_VERSION=1001    onCreate      --添加--  account  (v1.0代码不变)  onUpgrade(DATABASE_VERSION>1000)

                                                       onUpgrade   --添加--  member 

3、v3.0     DATABASE_VERSION=1002    onCreate      --添加--  account  (v1.0代码不变)  onUpgrade(DATABASE_VERSION>1001)

                                                       onUpgrade   --添加--  member (v2.0代码不变)

                                                       onUpgrade   --添加--  news

这样就可以解决问题了,第一版本的都在onCreate,其他版本新增的在onUpgrade,而且在onCreate执行onUpgrade。做判断是否执行onUpgrade该怎么判断呢,所以有了数据库版本的概念了,DATABASE_VERSION保存当前的数据库版本,只要当前的数据库版本比已经安装的数据库版本大时,就进入onUpgrade,这时还会把上一个数据库版本号(oldVersion)跟安装的数据库版本号(newVersion)做比较,不同的DATABASE_VERSION添加自己所需要的表(跨版本升级数据库)。

下面做一个简单的实例:

(1)、V1.0  : DATABASE_VERSION = 1000 添加一个favorite表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public  class  DBHelper  extends  SQLiteOpenHelper {
 
     private  static  final  String DATABASE_NAME =  "mall.db"
     private  static  final  int  DATABASE_VERSION =  1000 ;
 
     private  static  DBHelper instance =  null ;
 
 
     public  DBHelper(Context context) {
         super (context, DATABASE_NAME,  null , DATABASE_VERSION);
     }
     
     public  synchronized  static  DBHelper getInstance(Context context) {
         if  (instance ==  null ) {
             instance =  new  DBHelper(context);
         }
         return  instance;
     }
 
     @Override
     public  void  onCreate(SQLiteDatabase db) {
         db.execSQL(SQL.CREATE_TABLE_FAVORITE);
         
         // 若不是第一个版本安装,直接执行数据库升级
         // 请不要修改FIRST_DATABASE_VERSION的值,其为第一个数据库版本大小
         final  int  FIRST_DATABASE_VERSION =  1000 ;
         onUpgrade(db, FIRST_DATABASE_VERSION, DATABASE_VERSION);
     }
 
     @Override
     public  void  onUpgrade(SQLiteDatabase db,  int  oldVersion,  int  newVersion) {
         // 使用for实现跨版本升级数据库
         for  ( int  i = oldVersion; i < newVersion; i++) {
             switch  (i) {
 
             default :
                 break ;
             }
         }
     }
}

其中SQL.java是建表语句

1
2
3
4
5
6
7
8
9
10
11
12
public  class  SQL {
     public  static  final  String T_FAVORITE =  "favorite" ;
 
 
     public  static  final  String CREATE_TABLE_FAVORITE =
             "CREATE TABLE IF NOT EXISTS "  + T_FAVORITE +  "("  +
                     "id VARCHAR PRIMARY KEY, "  +
                     "title VARCHAR, "  +
                     "url VARCHAR, "  +
                     "createDate VARCHAR "  +
                     ")" ;
}

(2)、V2.0  : DATABASE_VERSION = 1001 在favorite表添加1个deleted字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public  class  DBHelper  extends  SQLiteOpenHelper {
 
     private  static  final  String DATABASE_NAME =  "mall.db"
     private  static  final  int  DATABASE_VERSION =  1001 ;
 
     private  static  DBHelper instance =  null ;
 
 
     public  DBHelper(Context context) {
         super (context, DATABASE_NAME,  null , DATABASE_VERSION);
     }
     
     public  synchronized  static  DBHelper getInstance(Context context) {
         if  (instance ==  null ) {
             instance =  new  DBHelper(context);
         }
         return  instance;
     }
 
     @Override
     public  void  onCreate(SQLiteDatabase db) {
         db.execSQL(SQL.CREATE_TABLE_FAVORITE);
         
         // 若不是第一个版本安装,直接执行数据库升级
         // 请不要修改FIRST_DATABASE_VERSION的值,其为第一个数据库版本大小
         final  int  FIRST_DATABASE_VERSION =  1000 ;
         onUpgrade(db, FIRST_DATABASE_VERSION, DATABASE_VERSION);
     }
 
     @Override
     public  void  onUpgrade(SQLiteDatabase db,  int  oldVersion,  int  newVersion) {
         // 使用for实现跨版本升级数据库
         for  ( int  i = oldVersion; i < newVersion; i++) {
             switch  (i) {
             case  1000 :
                 upgradeToVersion1001(db);
                 break ;
             default :
                 break ;
             }
         }
     }
     
     private  void  upgradeToVersion1001(SQLiteDatabase db){
         // favorite表新增1个字段
         String sql1 =  "ALTER TABLE " +SQL.T_FAVORITE+ " ADD COLUMN deleted VARCHAR" ;
         db.execSQL(sql1);
     }
}

(3)、V3.0  : DATABASE_VERSION = 1002 在favorite表添加message和type字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
public  class  DBHelper  extends  SQLiteOpenHelper {
 
     private  static  final  String DATABASE_NAME =  "mall.db"
     private  static  final  int  DATABASE_VERSION =  1002 ;
 
     private  static  DBHelper instance =  null ;
 
 
     public  DBHelper(Context context) {
         super (context, DATABASE_NAME,  null , DATABASE_VERSION);
     }
     
     public  synchronized  static  DBHelper getInstance(Context context) {
         if  (instance ==  null ) {
             instance =  new  DBHelper(context);
         }
         return  instance;
     }
 
     @Override
     public  void  onCreate(SQLiteDatabase db) {
         db.execSQL(SQL.CREATE_TABLE_FAVORITE);
         
         // 若不是第一个版本安装,直接执行数据库升级
         // 请不要修改FIRST_DATABASE_VERSION的值,其为第一个数据库版本大小
         final  int  FIRST_DATABASE_VERSION =  1000 ;
         onUpgrade(db, FIRST_DATABASE_VERSION, DATABASE_VERSION);
     }
 
     @Override
     public  void  onUpgrade(SQLiteDatabase db,  int  oldVersion,  int  newVersion) {
         // 使用for实现跨版本升级数据库
         for  ( int  i = oldVersion; i < newVersion; i++) {
             switch  (i) {
             case  1000 :
                 upgradeToVersion1001(db);
                 break ;
             case  1001 :
                 upgradeToVersion1002(db);
                 break ;
                 
             default :
                 break ;
             }
         }
     }
     
     private  void  upgradeToVersion1001(SQLiteDatabase db){
         // favorite表新增1个字段
         String sql1 =  "ALTER TABLE " +SQL.T_FAVORITE+ " ADD COLUMN deleted VARCHAR" ;
         db.execSQL(sql1);
     }
     private  void  upgradeToVersion1002(SQLiteDatabase db){
         // favorite表新增2个字段,添加新字段只能一个字段一个字段加,sqlite有限制不予许一条语句加多个字段
         String sql1 =  "ALTER TABLE " +SQL.T_FAVORITE+ " ADD COLUMN message VARCHAR" ;
         String sql2 =  "ALTER TABLE " +SQL.T_FAVORITE+ " ADD COLUMN type VARCHAR" ;
         db.execSQL(sql1);
         db.execSQL(sql2);
     }
}

就是这样,无论v1.0升级到v3.0,或者v2.0升级到3.0,还是v3.0直接安装,安装后的v3.0数据库结构都是一样的,理解透彻就是好啊,刚做sqlite数据库的肯定会遇到这些问题,所以在这里详细地写了一下,不过还是要注意一下,就是onUpgrade升级时候一定要写对,测试好,不然安装后的数据库都有问题就麻烦了。


其他android学习教程

android学习笔记(57)Handler消息传递机制

android学习笔记(56)android重写onConfigurationChange...

android学习笔记(55)android Configuration响应的系统设置的事...


作者:dyllove98 发表于2015/2/2 13:12:52 原文链接
阅读:0 评论:0 查看评论

相关 [android sqlite 数据库] 推荐:

Android SQLite数据库版本升级原理解析

- - CSDN博客推荐文章
Android使用SQLite数据库保存数据,那数据库版本升级是怎么回事呢,这里说一下. 安装v1.0,假设v1.0版本只有一个account表,这时走继承SQLiteOpenHelper的onCreate,不走onUpgrade. 1、v1.0(直接安装v1.0). 1、v1.0   -->  v2.0              不走onCreate,走onUpgrade.

Android学习笔记(六)SQLite

- - 博客园_首页
SQLite是一个极轻量型的数据库. 它在提供了和大型数据库相当的功能,还具有轻便、跨平台等优点,SQLite使用非常方便,并不需要我们像常规数据库(SQLServer,Mysql等)那样进行安装,在Android的JDK中,其实是已经包含了SQLite这个数据库的核心. 当然我们必须要强调一点,SQLite并不是只针对Android的,其实它还可以用在别的很多地方.

将Access转为SQLite数据库

- zhouding - 博客园-首页原创精华区
           SQLite是一个轻量型的数据库,各方面由于Access,对于小型网站来说,非常适合. 我今天决定将系统的数据库由Access转换为SQLite. 在网上搜索了一下,找到了DBManager这个工具,不得不说,这个软件确实好,很强大,在网上找注册码也找到半天,找不到一个.            只要将Access转换为SQLite,然后使用System.Data.SQLite.dll来访问数据库.

SQLite数据库存储引擎设计

- - searchdatabase
  SQLite是一个嵌入式库并且实现了零配置、无服务端和事务功能的SQL数据库引擎. 它在广泛领域内被使用,而且单线程读写性能与MySQL比肩,并且保证ACID性.   SQLite的存储后端是采用Btree实现,多个连接可以并发操作,但是同一时间只允许一个写着存在.   SQLite在硬盘上一个数据库一个文件,每个数据库文件头部保存有这个数据库的元信息,包括版本,大小,Btree根节点位置等等.

关于SQLite数据库的那些事儿

- - ITeye博客
在Android平台上,集成了一个嵌入式关系型数据库——SQLite. SQLite第一个Alpha版本诞生于2000年5月. 它是遵守ACID的关联式数据库管理系统,包含在一个相对小的C库中,同时是D.RichardHipp建立的公有领域项目. SQLite官方网站: http://www.sqlite.org/;SQLite中文社区:http://www.sqlite.com.cn/.

内存数据库FastDB和SQLite性能测评

- - CSDN博客数据库推荐文章
在很多项目中,经常会碰到这样的需求,需要对大量数据进行快速存储、查询、删除等操作,特别是在一些针对诸如运营商、银行等大型企业的应用中,这些需求尤为常见. 比如智能网中的大量在线并发用户的数据管理、软交换平台中的在线信息交互、宽带/3G等数据网中在线用户行为记录等等. 针对这些情形,我们通常需要选择高性能的数据库产品,而且通常需要使用内存数据库,顾名思义,内存数据库指的是所有的数据访问控制都在内存中进行,这是与磁盘数据库相对而言的,磁盘数据库虽然也有一定的缓存机制,但都不能避免从外设到内存的交换,而这种交换过程对性能的损耗是致命的,目前主流数据库如SYBASE、ORACLE等都有这种缓存机制,如将特定表绑定一定的缓存,从而在一定程度上改善数据吞吐性能.

Sqlite数据库分页查询(ListView分页显示数据)

- - CSDN博客推荐文章
今天项目中遇到个问题,之前数据量不算多的时候,ListView显示正常,但是当数据量很大得分时候,进入画面,显示数据比较慢,. 而且不能放在UI线程中去拿数据,用子线程去拿把,画面出来了,但是数据要等很久才会出来,因此,这样给人的体验很不好,算不上好的设计. 因此,查了一下,关于数据库分页ListView分页.

Android数据的四种存储方式SharePreference、SQLite、Content Provider和File (二) —— SQLite

- stony - 博客园-首页原创精华区
  SQLite是一种转为嵌入式设备设计的轻型数据库,其只有五种数据类型,分别是:.     INTEGER: 整数.   在SQLite中,并没有专门设计BOOLEAN和DATE类型,因为BOOLEAN型可以用INTEGER的0和1代替true和false,而DATE类型则可以拥有特定格式的TEXT、REAL和INTEGER的值来代替显示,为了能方便的操作DATE类型,SQLite提供了一组函数,详见:http://www.sqlite.org/lang_datefunc.html.

Android-小项目之迷你英文词典-使用existing sqlite database-github第三库android-sqlite-asset-helper

- - CSDN博客移动开发推荐文章
将已有的词典数据库文件,用到项目中. 谷歌搜索“android existing sqlite database”. 但是,如果 数据库文件在 assets 目录下,该如何做呢. private EditText mEditText; //输入框. private TextView mReslutView; //显示查询结果.

Android项目快速开发框架探索(Mysql + OrmLite + Hessian + Sqlite)

- - 博客园_首页
结合之前所用的ormlite和hessian,再加上SAE已经支持JAVA,把服务端切换到JAVA,也就有了本文. 使用hessian来做数据传输,ormlite来实现客户端与服务端的数据存储,极大的减少了CRUD工作. 本文为探索贴,未正式用于大型项目,欢迎大家讨论使用.   欢迎转载,但请保留文章原始出处:).