Android 数据库升级解决方案

转自: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,给定表名,更新的列名,就可以实现数据库表的更新。

 

[java] view plaincopy
  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.   
  20.         // 1, Rename table.  
  21.         String tempTableName = tableName + "_temp";  
  22.         String sql = "ALTER TABLE " + tableName +" RENAME TO " + tempTableName;  
  23.         execSQL(db, sql, null);  
  24.   
  25.         // 2, Create table.  
  26.         onCreateTable(db);  
  27.   
  28.         // 3, Load data  
  29.         sql =   "INSERT INTO " + tableName +  
  30.                 " (" + columns + ") " +  
  31.                 " SELECT " + columns + " FROM " + tempTableName;  
  32.   
  33.         execSQL(db, sql, null);  
  34.   
  35.         // 4, Drop the temporary table.  
  36.         execSQL(db, "DROP TABLE IF EXISTS " + tempTableName, null);  
  37.   
  38.         db.setTransactionSuccessful();  
  39.     }  
  40.     catch (SQLException e)  
  41.     {  
  42.         e.printStackTrace();  
  43.     }  
  44.     catch (Exception e)  
  45.     {  
  46.         e.printStackTrace();  
  47.     }  
  48.     finally  
  49.     {  
  50.         db.endTransaction();  
  51.     }  
  52. }  

 

 

得到数据库表的列名

 

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

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

 

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()方法的实现如下:

 

[java] view plaincopy
  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.   
  8.   
  9. public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)  
  10. {  
  11.     int upgradeVersion  = oldVersion;  
  12.   
  13.     if (18 == upgradeVersion) {  
  14.         // Create table C  
  15.         String sql = "CREATE TABLE ...";  
  16.         db.execSQL(sql);  
  17.         upgradeVersion = 19;  
  18.     }  
  19.   
  20.     if (20 == upgradeVersion) {  
  21.         // Modify table C  
  22.         upgradeVersion = 20;  
  23.     }  
  24.   
  25.     if (upgradeVersion != newVersion) {  
  26.         // Drop tables  
  27.         db.execSQL("DROP TABLE IF EXISTS " + tableName);  
  28.         // Create tables  
  29.         onCreate(db);  
  30.     }  
  31. }  


从上面的代码可以看到,我们在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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/398121.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[php入门] 3、WAMP中的集成MySQL相关基础操作

前言&#xff1a;本文以小白视角了解WAMP集成开发环境中的MYSQL&#xff0c;涉及的面广而浅&#xff0c;算是导读性质。 1、启动运行熟悉WAMP中的MySQL 先有库、再有表、数据最终以记录的形式插入表中。其中对数据进行操作使用SQL语句&#xff0c;SQL是结构化的查询语言。 在wa…

apns java 证书_APNS推送服务证书制作 图文详解教程(新)

iOS消息推送的工作机制可以简单的用下图来概括&#xff1a;Provider是指某个iPhone软件的Push服务器&#xff0c;APNS是Apple Push Notification Service的缩写&#xff0c;是苹果的服务器。上图可以分为三个阶段&#xff1a;第一阶段&#xff1a;应用程序把要发送的消息、目的…

Android近场通信---NFC基础(二)(转)

转自 http://blog.csdn.net/think_soft/article/details/8171256 应用程序如何调度NFC标签 当标签调度系统完成对NFC标签和它的标识信息封装的Intent对象的创建时&#xff0c;它会把该Intent对象发送给感兴趣的应用程序。如果有多个应用程序能够处理该Intent对象&#xff0c;就…

:base(参数)

:base(必须有值)&#xff1a;作用是将父类的值继承过来&#xff0c;如果不在构造函数中加入&#xff1a;base(变量) 的话&#xff0c;原父类中的 Model则无法继承过来。 例如&#xff1a;在父类MSG_Model,有连个属性&#xff0c;如图 1.子类构造函数不写:base(参数) 2.1.子类构…

MVC5 + EF6 完整入门教程三

MVC5 EF6 完整入门教程三 原文:MVC5 EF6 完整入门教程三期待已久的EF终于来了。 学完本篇文章&#xff0c;你将会掌握基于EF数据模型的完整开发流程。 本次将会完成EF数据模型的搭建和使用。 基于这个模型&#xff0c;将之前的示例添加数据库查询验证功能。 文章提纲 概…

Expect 教程中文版

http://blog.csdn.net/chinalinuxzend/article/details/1842588原贴&#xff1a;http://blog.chinaunix.net/u/13329/showart.php?id110100 Expect 教程中文版[From] http://www.linuxeden.com/edu/doctext.php?docid799  本教程由*葫芦娃*翻译&#xff0c;并做…

IntelliTrace 调试、定位异常

最近看了一个开源数据库管理&#xff0c;然后没有认真看它的配置环境&#xff0c;想看看是什么东西&#xff0c; 然后发现有类型转换的错误&#xff0c;但是一下子也定位不到哪里出错&#xff1f; 所以对于这种一下子找不到异常在哪里的&#xff0c;可以使用intellitrace智能跟…

zedboard--zynq使用自带外设IP让ARM PS访问FPGA(八) 转载

文章来源 http://blog.chinaaet.com/detail/34609 熟悉了xps的操作&#xff0c;IP添加&#xff0c;总线连接设置&#xff0c;图形化方法检查&#xff08;open graphical design view&#xff09;&#xff0c;检查总线及端口连接。 在file下面的图标中&#xff0c;打开导出到SDK…

[php入门] 4、HTML基础入门一篇概览

[php入门] 1、从安装开发环境环境到&#xff08;庄B&#xff09;做个炫酷的登陆应用 [php入门] 2、基础核心语法大纲 [php入门] 3、WAMP中的集成MySQL相关基础操作 1、HTML的作用   HTML是超文本标记语言&#xff0c;主要用于制作页面结构&#xff1b;而经常与之一起用的CSS是…

Python3 爬虫爬取中国图书网(淘书团) 记录

本人为一名刚开始学Python爬虫的小白&#xff0c;开贴仅为记录下自己的学习历程&#xff0c;方便做review 要爬取链接&#xff1a;http://tuan.bookschina.com/ 要爬取内容&#xff1a; 图书名称&#xff0c; 图书价格&#xff0c; 以及对应预览图的link 本文用到py packages: …

java连接字符串_Java如何连接字符串

Java中的连接是将两个字符串连接在一起的操作。您可以使用加()运算符或String的concat ()方法来连接字符串。使用运算符使用运算符是在Java中连接两个字符串的最常用方法。您可以提供变量&#xff0c;数字或字符串文字(始终用双引号括起来)。例如&#xff0c;要组合字符串“I’…

分布式之延时任务方案解析

每天学习一点点 编程PDF电子书、视频教程免费下载&#xff1a;http://www.shitanlife.com/code引言 在开发中&#xff0c;往往会遇到一些关于延时任务的需求。例如 生成订单30分钟未支付&#xff0c;则自动取消生成订单60秒后,给用户发短信对上述的任务&#xff0c;我们给一个专…

mysql 搭建日志服务器_一、架构01-搭建日志服务器Rsyslog

搭建日志服务器1、环境配置环境&#xff1a;node01 192.168.32.132 rsyslog服务器node02 192.168.32.128 rsyslog客户端2、node01、node02安装rsyslog软件包[rootnode01 ~]# yum install -y rsyslog[rootnode02 ~]# yum install -y rsyslog3、修改node01上rsyslog的配置文件…

python异常值均值填充_Python 异常值分析

异常值分析是检验数据是否有录入错误以及含有不合常理的数据。忽视异常值的存在是十分危险的&#xff0c;不加剔除地把异常值包括进数据的计算分析过程中&#xff0c;对结果会产生不良影响&#xff1b;重视异常值的出现&#xff0c;分析其产生的原因&#xff0c;常常成为发现问…

近期学习清单

2019独角兽企业重金招聘Python工程师标准>>> 框架 1.编写xml性质的ioc容器demo&#xff08;附上博文一篇&#xff09; 2.编写unity形式的ioc容器demo&#xff08;附上博文一篇&#xff09; 3.编写自己的orm框架 c#语言特性 1.大量阅读有关枚举类&#xff0c;查询类…

java同名函数_浅谈Java 继承接口同名函数问题

在Java中如果一个类同时继承接口A与B&#xff0c;并且这两个接口中具有同名方法&#xff0c;会怎么样&#xff1f;动手做实验&#xff1a;interface A{void fun();}interface B{void fun();}interface C extends A,B{}public class Test implements C{Overridepublic void fun(…

NopCommerce开源项目中很基础但是很实用的C# Helper方法

NopCommerce是啥&#xff1f; nopCommerce是最好的开源电子商务购物 系统。nopCommerce免费提供。今天&#xff0c;它是最好和最流行的ASP.NET电子商务软件。它已被下载超过180万次&#xff01; nopCommerce是一个完全可定制的购物系统。它稳定且高度可用。nopCommerce是一个开…

写一个函数,输入int型,返回整数逆序后的字符串

2019独角兽企业重金招聘Python工程师标准>>> 刚刚看到一个面试题&#xff1a;写一个函数&#xff0c;输入int型&#xff0c;返回整数逆序后的字符串。如&#xff1a;输入123&#xff0c;返回“321”。 要求必须用递归&#xff0c;不能用全局变量&#xff0c;输入必须…

VS2013 使用QCustomPlot等三方库如何配置

QCustomPlot 是一个小巧好用的 QT 图表插件。用来画曲线图、趋势图、坐标图、柱状图等类似二维图的库。实现大部分的2维图形绘制。使用时&#xff0c;我们在程序中写完相关调用的代码后&#xff0c;只需将 QCunstomPlot.cpp 和 QCustomPlot.h 两个文件加入工程&#xff0c;正常…

Php RSS

RSS 聚合最近非常流行&#xff0c;因此至少对 RSS 及其工作方式有所了解是一名 PHP 开发人员的迫切需要。本文介绍了 RSS 基础知识、RSS 众多用途中的一些用途、如何使用 PHP 从数据库创建 RSS 提要&#xff0c;以及如何使用 XML_RSS 模块读取现有 RSS 提要并将其转换为 HTML。…