转自:http://blog.csdn.net/leehong2005/article/details/9128501
请考虑如下情况:
在数据库升级时,不同版本的数据库,他们定义的表结构完全可能是不一样的,比如V1.0的表A有10个column,而在V1.1的表A有12个colum,在升级时,表A增加了两列,此时我们应该怎么做呢。
总体思路
1,将表A重命名,改了A_temp。
2,创建新表A。
3,将表A_temp的数据插入到表A。
下面代码列出了更新表的实现,upgradeTables,给定表名,更新的列名,就可以实现数据库表的更新。
- /**
- * 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。
- 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()方法的实现如下:
- // 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()方法中,删除表时,注意使用事务处理,使得修改能立即反应到数据库文件中。
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数据库升级不丢失数据解决方案 https://mp.csdn.net/mp_blog/creation/editor/124272815
此文档可以解决数据库兼容及升级问题,并且内容包括有多种解决方案!
Android系统从一开始就内置了SQLite数据库,为应用程序提供了方便的数据持久化解决方案。 该Demo的核心是创建一个SQLiteOpenHelper的子类,该类负责创建和升级数据库。在这个子类中,通常需要实现onCreate()和...
1.2.4 Android移动Web项目开发的三种解决方案:Native, Web和Hybrid优缺陷分析 4 1.2.5国内外应用现状 6 1.2.6 研究现状总结 7 1.3研究目标与内容 7 1.3.1多窗口浏览器模式的实现机制 7 1.3.2跨域交互即缓存处理方法...
前言 Android开发中我们或多或少都会接触到数据库。Android中提供了一个占用内存极小的关系型数据库-SQLite。...官网上的介绍,greenDAO 是一个将对象映射到 SQLite 数据库中的轻量且快速的 ORM 解决方案。(gr
唯一的解决方案是植根设备并更改权限(例如:https : //goo.gl/Ksk0Bm)或升级到Android 5+并使用SAF模式(https://goo.gl/fexsry)。 或者–在您的外部SD卡上创建以下目录: Android / data / ...
十一、网狐荣耀版vs生成解决方案时出现“出现未能写入日志,请求的操作无法在使用用户映射区域打开的文件上执行“错误 一、定位文件,看是不是只读。 二、删除文件试一下,看看是不是文件被占用,如果删除不了,...
后期维护与升级:定期对系统进行维护和升级,确保系统稳定运行。 六、预期效果 通过本方案的实施,可以实现以下预期效果: 提高停车效率:用户可以快速找到空车位并预订,避免长时间寻找车位的现象。 降低运营成本...
唯一的解决方案是根设备并更改权限(例如:https://goo.gl/Ksk0Bm)或升级到Android 5+并使用SAF模式(https://goo.gl/fexsry)。 或者 - 创建以下目录(在外部SD卡上): Android / data / ...
智能家居物联网实验室建设方案 1概述 3G是现在社会最流行的无线传输方式,可以实现随时随地上互联网,打电话,接电话 ,发短信等各种无线通信等功能,特别是google公司开发的android操作系统,号称给将 每个人的口袋...
它包含:移动端APP,采用原生模式开发,覆盖使用iOS 及Android系统的移 动终端;后台系统,针对平台日常运营维护的平台后台,针对入驻店铺管理的商家后台,独立并行;移动端H5,能够灵活部署于微信及其他APP… 运维...
布谷科技全面分析市场趋势、强势推出更符合市场需求的一对-视频聊天交友解决方案一布谷- 对一 视频交友系统。 布谷一对一系统 布谷直播系统源码前端功能说明: 登入注册:手机验证码登入、编辑个人信息、上传头像 ...