开发者社区> 范大脚脚> 正文

Android 数据库升级解决方案

简介:
+关注继续查看

请考虑如下情况:

在数据库升级时,不同版本的数据库,他们定义的表结构完全可能是不一样的,比如V1.0的表A有10个column,而在V1.1的表A有12个colum,在升级时,表A增加了两列,此时我们应该怎么做呢。

总体思路

 1,将表A重命名,改了A_temp。

2,创建新表A。

3,将表A_temp的数据插入到表A。

下面代码列出了更新表的实现,upgradeTables,给定表名,更新的列名,就可以实现数据库表的更新。

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
/**
 * Upgrade tables. In this method, the sequence is:
 * <b>
 * <p>[1] Rename the specified table as a temporary table.
 * <p>[2] Create a new table which name is the specified name.
 * <p>[3] Insert data into the new created table, data from the temporary table.
 * <p>[4] Drop the temporary table.
 * </b>
 *
 * @param db The database.
 * @param tableName The table name.
 * @param columns The columns range, format is "ColA, ColB, ColC, ... ColN";
 */
protected void upgradeTables(SQLiteDatabase db, String tableName, String columns)
{
    try
    {
        db.beginTransaction();
 
        // 1, Rename table.
        String tempTableName = tableName + "_temp";
        String sql = "ALTER TABLE " + tableName +" RENAME TO " + tempTableName;
        execSQL(db, sql, null);
 
        // 2, Create table.
        onCreateTable(db);
 
        // 3, Load data
        sql =   "INSERT INTO " + tableName +
                " (" + columns + ") " +
                " SELECT " + columns + " FROM " + tempTableName;
 
        execSQL(db, sql, null);
 
        // 4, Drop the temporary table.
        execSQL(db, "DROP TABLE IF EXISTS " + tempTableName, null);
 
        db.setTransactionSuccessful();
    }
    catch (SQLException e)
    {
        e.printStackTrace();
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
    finally
    {
        db.endTransaction();
    }
}

 

得到数据库表的列名

我们可以通过SQL表得到表的列名。 这里需要注意的一点,int columnIndex = c.getColumnIndex("name"); 这里根据name去取得index。 

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
protected String[] getColumnNames(SQLiteDatabase db, String tableName)
{
    String[] columnNames = null;
    Cursor c = null;
 
    try
    {
        c = db.rawQuery("PRAGMA table_info(" + tableName + ")"null);
        if (null != c)
        {
            int columnIndex = c.getColumnIndex("name");
            if (-1 == columnIndex)
            {
                return null;
            }
 
            int index = 0;
            columnNames = new String[c.getCount()];
            for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext())
            {
                columnNames[index] = c.getString(columnIndex);
                index++;
            }
        }
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
    finally
    {
        closeCursor(c);
    }
 
    return columnNames;
}

  

upgradeTables方法应该是在onUpgrade方法中去调用。 

数据库升级的意义 

在应用程序开发的过程中,数据库的升级是一个很重要的组成部分(如果用到了数据库),因为程序可能会有V1.0,V2.0,当用户安装新版本的程序后,必须要保证用户数据不能丢失,对于数据库设计,如果发生变更(如多添加一张表,表的字段增加或减少等),那么我们必须想好数据库的更新策略。

1,定义数据库版本

数据库的版本是一个整型值,在创建SQLiteOpenHelper时,会传入该数据库的版本,如果传入的数据库版本号比数据库文件中存储的版本号大的话,那么SQLiteOpenHelper#onUpgrade()方法就会被调用,我们的升级应该在该方法中完成。

2,如何写升级逻辑

假如我们开发的程序已经发布了两个版本:V1.0,V1.2,我们正在开发V1.3。每一版的数据库版本号分别是18,19,20。

对于这种情况,我们应该如何实现升级?

用户的选择有:                   

1) V1.0 -> V1.3  DB 18 -> 20                  

2) V1.1 -> V1.3  DB 19 -> 20      

3,注意

数据库的每一个版本所代表的数据库必须是定义好的,比如说V18的数据库,它可能只有两张表TableA和TableB,如果V19要添加一张表TableC,如果V20要修改TableC,那么每一个版本所对应的数据库结构如下:

V18  --->  TableA, TableB

V19  --->  TableA, TableB, TableC

V20  --->  TableA, TableB, TableC (变更)

onUpgrade()方法的实现如下:

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
    // Pattern for upgrade blocks:
//
//    if (upgradeVersion == [the DATABASE_VERSION you set] - 1){
//        .. your upgrade logic..
//        upgradeVersion = [the DATABASE_VERSION you set]
//    }
 
 
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
    int upgradeVersion  = oldVersion;
 
    if (18 == upgradeVersion) {
        // Create table C
        String sql = "CREATE TABLE ...";
        db.execSQL(sql);
        upgradeVersion = 19;
    }
 
    if (20 == upgradeVersion) {
        // Modify table C
        upgradeVersion = 20;
    }
 
    if (upgradeVersion != newVersion) {
        // Drop tables
        db.execSQL("DROP TABLE IF EXISTS " + tableName);
        // Create tables
        onCreate(db);
    }
}

  

从上面的代码可以看到,我们在onUpgrade()方法中,处理了数据库版本从18 -> 20的升级过程,这样做的话,不论用户从18 -> 20,还是从19 -> 20,最终程序的数据库都能升级到V20所对应的数据库结构。  

4,如何保证数据不丢失

这是很重要的一部分,假设要更新TableC表,我们建议的做法是:       

1) 将TableC重命名为TableC_temp

       SQL语句可以这样写:ALERT TABLE TableC RENAME TO TableC_temp;

2) 创建新的TableC表

3) 将数据从TableC_temp中插入到TableC表中

       SQL语句可以这样写:INSERT INTO TableC (Col1, Col2, Col3) SELECT (Col1, Col2, Col3) FROM TableC_temp;                

                   
经过这三步,TableC就完成了更新,同时,也保留了原来表中的数据。  

注意:

在onUpgrade()方法中,删除表时,注意使用事务处理,使得修改能立即反应到数据库文件中。       



本文转自java豆子博客园博客,原文链接:http://www.cnblogs.com/error404/p/3738630.html,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Android Studio开发APP启动程序时开屏简单动画效果快速有效解决方案
Android Studio开发APP启动程序时开屏简单动画效果快速有效解决方案
313 0
Android studio中ADB不幸运终止app程序解决方案
Android studio中ADB不幸运终止app程序解决方案
32 0
Android绘制竖直虚线完美解决方案—自定义View
开发中我们经常会遇到绘制虚线的需求,一般我们使用一个drawable文件即可实现,下面我会先列举常规drawable文件的实现方式。
400 0
Android APP启动黑屏及解决方案
相信做过Android的朋友都知道,当一个APP启动时,界面会首先展示一个白屏或者黑屏,然后再进入欢迎页,稍作停留最后进入APP主页。那么这个黑屏或者白屏到底是怎么一回事呢?
150 0
谈一谈 Android 嵌套 Intent 以及解决方案
谈一谈 Android 嵌套 Intent 以及解决方案
78 0
Android SDK Manager无法显示可供下载的未安装SDK解决方案
Android SDK Manager无法显示可供下载的未安装SDK解决方案
125 0
安卓关于Bitmap.isRecycled()空指针报错的解决方案
起因是我在开发功能需要使用Bitmap的方法:
110 0
android retrofit 请求返回String数据中文乱码解决方案
问题来源 focus 应用中核心的部分是,网络请求订阅的xml文件内容,然后解析xml文件存储到本地数据库。
111 0
关于安卓Handler内存泄漏及解决方案
Handler是安卓中常见的实现异步操作的方法,使用简单,但是操作不注意很容易造成内存泄漏。
48 0
Android 全埋点解决方案(3)
Android 全埋点解决方案
177 0
+关注
范大脚脚
文章
问答
视频
文章排行榜
最热
最新
相关电子书
更多
Android组件化实现
立即下载
蚂蚁聚宝Android秒级编译—— Freeline
立即下载
Android插件化:从入门到放弃
立即下载