请考虑如下情况:

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

总体思路

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

2,创建新表A。

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

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

  1. /**
  2. * Upgrade tables. In this method, the sequence is:
  3. * <b>
  4. * <p>[1] Rename the specified table as a temporary table.
  5. * <p>[2] Create a new table which name is the specified name.
  6. * <p>[3] Insert data into the new created table, data from the temporary table.
  7. * <p>[4] Drop the temporary table.
  8. * </b>
  9. *
  10. * @param db The database.
  11. * @param tableName The table name.
  12. * @param columns The columns range, format is "ColA, ColB, ColC, ... ColN";
  13. */
  14. protected void upgradeTables(SQLiteDatabase db, String tableName, String columns)
  15. {
  16. try
  17. {
  18. db.beginTransaction();
  19. // 1, Rename table.
  20. String tempTableName = tableName + "_temp";
  21. String sql = "ALTER TABLE " + tableName +" RENAME TO " + tempTableName;
  22. execSQL(db, sql, null);
  23. // 2, Create table.
  24. onCreateTable(db);
  25. // 3, Load data
  26. sql =   "INSERT INTO " + tableName +
  27. " (" + columns + ") " +
  28. " SELECT " + columns + " FROM " + tempTableName;
  29. execSQL(db, sql, null);
  30. // 4, Drop the temporary table.
  31. execSQL(db, "DROP TABLE IF EXISTS " + tempTableName, null);
  32. db.setTransactionSuccessful();
  33. }
  34. catch (SQLException e)
  35. {
  36. e.printStackTrace();
  37. }
  38. catch (Exception e)
  39. {
  40. e.printStackTrace();
  41. }
  42. finally
  43. {
  44. db.endTransaction();
  45. }
  46. }

得到数据库表的列名

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

  1. protected String[] getColumnNames(SQLiteDatabase db, String tableName)
  2. {
  3. String[] columnNames = null;
  4. Cursor c = null;
  5. try
  6. {
  7. c = db.rawQuery("PRAGMA table_info(" + tableName + ")", null);
  8. if (null != c)
  9. {
  10. int columnIndex = c.getColumnIndex("name");
  11. if (-1 == columnIndex)
  12. {
  13. return null;
  14. }
  15. int index = 0;
  16. columnNames = new String[c.getCount()];
  17. for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext())
  18. {
  19. columnNames[index] = c.getString(columnIndex);
  20. index++;
  21. }
  22. }
  23. }
  24. catch (Exception e)
  25. {
  26. e.printStackTrace();
  27. }
  28. finally
  29. {
  30. closeCursor(c);
  31. }
  32. return columnNames;
  33. }

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. // Pattern for upgrade blocks:
  2. //
  3. //    if (upgradeVersion == [the DATABASE_VERSION you set] - 1){
  4. //        .. your upgrade logic..
  5. //        upgradeVersion = [the DATABASE_VERSION you set]
  6. //    }
  7. public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
  8. {
  9. int upgradeVersion  = oldVersion;
  10. if (18 == upgradeVersion) {
  11. // Create table C
  12. String sql = "CREATE TABLE ...";
  13. db.execSQL(sql);
  14. upgradeVersion = 19;
  15. }
  16. if (20 == upgradeVersion) {
  17. // Modify table C
  18. upgradeVersion = 20;
  19. }
  20. if (upgradeVersion != newVersion) {
  21. // Drop tables
  22. db.execSQL("DROP TABLE IF EXISTS " + tableName);
  23. // Create tables
  24. onCreate(db);
  25. }
  26. }

从上面的代码可以看到,我们在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()方法中,删除表时,注意使用事务处理,使得修改能立即反应到数据库文件中。

SQL语句

由于Android是使用开源的SQLite3作为其数据库,所以,我们在开发数据库模块时,一定要注意SQLite3支持哪些关键字,函数等,不是所有的关键字,SQLite都是支持的。

下面列出了一些参考链接:

SQLite3官方文档:http://sqlite.org/

W3CSchool网站:http://www.w3school.com.cn/sql/index.asp/

SQL语句写得好坏能直接影响到数据库的操作。我曾经就遇到过SQL语句影响查询性能,更新3000条记录,用时30移左右,但在对WHERE条件的字段加上索引后,性能提升到3~4秒。

参考:http://androidll.iteye.com/blog/1570943

Android 数据库升级解决方案的更多相关文章

  1. Android数据库升级不丢失数据解决方案

    在Android开发中,sqlite至关重要,增删查改不多说,难点在于,1,并发,多个线程同时操作数据库.2,版本升级时,如果数据库表中新加了个字段,如何在不删除表的情况下顺利过渡,从而不丢失数据. ...

  2. Android数据库升级

    随着Android应用版本的迭代,经常遇到数据库表结构发生改变,或者一些指定的表数据需要更新.这也就引出一个问题Android数据库的更新问题. Android数据库升级分类 Android数据库更新 ...

  3. 优雅的处理Android数据库升级的问题

    原始完成于:2015-04-27 19:28:22 提供一种思路,优雅的处理Android数据库升级的问题,直接上代码: 1 package com.example.databaseissuetest ...

  4. Android数据库升级、降级、创建(onCreate() onUpgrade() onDowngrade())[4]

    数据库版本升级对软件的管理操作. 我们手机经常会收到xxx软件升级什么的提醒,你的软件版本更新,同时你的数据库对应的版本也要相应的更新. 数据库版本更新需要主要的问题: 软件的1.0版本升级到1.1版 ...

  5. Android数据库升级、降级、创建(onCreate() onUpgrade() onDowngrade())的注意点

    以下内容可以作为面试官在面试的时候的问题,感觉比较好,是比较常用的知识点,可以用来考察基础是否扎实. 也可以程序猿学习.开发中的注意点.因为稍微不注意,就有可能导致数据库不能用. DBAdapter. ...

  6. Android数据库升级实例

    第一部分 Andoird的SQLiteOpenHelper类中有一个onUpgrade方法.帮助文档中只是说当数据库升级时该方法被触发.经过实践,解决了我一连串的疑问: 1. 帮助文档里说的“数据库升 ...

  7. Android 数据库升级中数据保持和导入已有数据库

    一.数据库升级: 在我们的程序中,或多或少都会涉及到数据库,使用数据库必定会涉及到数据库的升级,数据库升级带来的一些问题,如旧版本数据库的数据记录的保持,对新表的字段的添加等等一系列问题,还记得当我来 ...

  8. Android数据库升级,数据不丢失解决方案

    假设要更新TableC表,建议的做法是: 1) 将TableC重命名为TableC_temp SQL语句可以这样写:ALERT TABLE TableC RENAME TO TableC_temp; ...

  9. android数据库升级的措辞

    在基类table增加upgrade操作: public abstract class DbBaseTable { private static final String TAG = "DbB ...

随机推荐

  1. 周赛-The Number Off of FFF 分类: 比赛 2015-08-02 09:27 3人阅读 评论(0) 收藏

    The Number Off of FFF Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Other ...

  2. setprecision(int n)等格式函数用法 分类: POJ 2015-06-11 10:56 17人阅读 评论(0) 收藏

    **这些用法前最好用 #include <iostream>    //不要用iostream.h ,会出现好多问题 #include <iomanip> // io 流控制头 ...

  3. js post提交页面

    function post(URL, PARAMS) { var temp = document.createElement("form"); temp.action = URL; ...

  4. OracleHelper

    /// <summary> /// OracleServer数据库访问的通用工具类 /// </summary> public abstract class OracleHel ...

  5. LINUX 产生PPM 驱动例子

    APP: //author:DriverMonkey //phone:13410905075 //mail:bookworepeng@Hotmail.com //qq:196568501 #inclu ...

  6. 乘号在python中的用法,用乘号将元素重复在列表中

    #里面:>>> a=['*5] >>> a ['] >>> a=['0,'*5] >>> a ['0,0,0,0,0,'] #外 ...

  7. VM安装失败

    出现:VMware安装失败 “Failed to create the requested registry key Key:installer Error:1021" 解决: 开始--运行 ...

  8. VC++检测当前网络状态

    VC获得本机网络连接状态 转载:http://www.cppblog.com/wrhwww/archive/2010/12/02/135230.html //本机网络连接类型(成功) #define ...

  9. C#大纲

    输入输出--数据类型--变量与常量--运算符表达式--语句(顺序.分支.循环)--数组--函数--结构体一.输入与输出.Console.ReadLine();Console.WriteLine();C ...

  10. netsh winsock reset 11003

    netsh winsock reset 11003 http://files.cnblogs.com/xsmhero/winsock.zip