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,如需转载请自行联系原作者

相关文章
|
19天前
|
安全 Shell Android开发
Android系统 init.rc sys/class系统节点写不进解决方案和原理分析
Android系统 init.rc sys/class系统节点写不进解决方案和原理分析
30 0
|
1月前
|
XML Android开发 数据格式
android点击FrameLayout、LinearLayout等父布局没响应的原因以及解决方案
android点击FrameLayout、LinearLayout等父布局没响应的原因以及解决方案
32 2
|
2月前
|
存储 SQL 关系型数据库
TiDB的优势:为何选择TiDB作为您的数据库解决方案
【2月更文挑战第25天】随着数据规模的不断增长和业务需求的日益复杂化,现代企业对数据库系统的扩展性、高可用以及分布式处理能力提出了更高的要求。TiDB作为一个新型的开源分布式数据库,以其独特的设计理念与卓越的技术特性,在众多数据库解决方案中脱颖而出。本文将深入剖析TiDB的核心优势,探讨其如何帮助企业从容应对海量数据挑战、实现无缝水平扩展、保障服务高可用性,并提供灵活一致的事务支持。
|
2月前
|
网络协议 关系型数据库 MySQL
如何实现无公网ip远程访问本地安卓Termux部署的MySQL数据库【内网穿透】
如何实现无公网ip远程访问本地安卓Termux部署的MySQL数据库【内网穿透】
|
2月前
|
Oracle 关系型数据库 分布式数据库
分布式数据库集成解决方案
分布式数据库集成解决方案
210 0
|
4月前
|
存储 DataWorks 监控
DataWorks,一个 polar db 有上万个数据库,解决方案
DataWorks,一个 polar db 有上万个数据库,解决方案
|
4月前
|
存储 数据库连接 数据库
Android数据存储:解释SQLite数据库在Android中的使用。
Android数据存储:解释SQLite数据库在Android中的使用。
43 0
|
6天前
|
Android开发
Android中Glide加载Https图片失败的解决方案
Android中Glide加载Https图片失败的解决方案
14 1
|
10天前
|
存储 运维 Kubernetes
多态关联在数据库设计中的应用和解决方案
多态关联在数据库设计中的应用和解决方案
17 0
|
19天前
|
安全 编译器 API
Android HAL深入探索(5): 调试HAL报错与解决方案
Android HAL深入探索(5): 调试HAL报错与解决方案
25 1