Android数据库更新并保留原来数据的实现

来源:互联网 发布:oracle sql 变量 编辑:程序博客网 时间:2024/06/06 07:19

本人采用的是:Android ORM(框架)    GreenDao

GreenDao优点:Android大大优化 ,最小的内存使用 ,非常高的性能优势。


官网地址:http://greendao-orm.com/features/

项目地址:https://github.com/greenrobot/greenDAO


greenDaoMaster深入学习:http://blog.csdn.net/krislight/article/details/9391455


场景描述:这次项目中要在用户表中添加两个新字段address和age,但是数据库更新导致app升级时需要考虑数据库之前老数据的备份,所以我们要能够把

旧版本app所使用的数据库迁移到新升级版本app能够使用的数据库。换言之,我们要在原来数据库表的基础上新增两个字段,并赋予他们默认值。




第一步:

我们升级数据库时第一步一般是升级数据库版本号:我之前使用的数据库版本号是6,所以我现在升级的版本号是:

public static final int SCHEMA_VERSION = 7;


第二步:

 //定义在原来的表上要添加的新字段address和age,所以新创建user表
    private static final String CREATE_USER = "create table USER(_id INTEGER PRIMARY KEY,NAME TEXT NOT NULL,SEX TEXT,LOGINDATE INTEGER,ADDRESS TEXT,AGE INTEGER);";

    //修改原来的user表名改为_temp_user临时表名
    private static final String CREATE_TEMP_USER = "alter table USER rename to _temp_user";
    
    //把临时备份表中的数据copy到新创建的数据库表中
    private static final String INSERT_DATA = "insert into USER select *,'' from _temp_user";
    
    //删除临时备份表
    private static final String DROP_USER = "drop table _temp_user";



第三步:

在Andoird的SQLiteOpenHelper类中有一个onUpgrade方法中:

@Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
//            dropAllTables(db, true);
//            onCreate(db);
            switch(newVersion){
                case 7:
                   db.execSQL(CREATE_TEMP_USER); //第一步将旧表改为临时表

                   db.execSQL(CREATE_USER); //第二步创建新表(新添加的字段或去掉 的字段)

                   db.execSQL(INSERT_DATA); //第三步将旧表中的原始数据保存到新表中以防遗失

                   db.execSQL(DROP_USER); //第四步删除临时备份表
                   break;
            }
        }


OK!完结!




详细描述请看下面这篇文章:


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

1. 帮助文档里说的“数据库升级”是指什么?


你开发了一个程序,当前是1.0版本。该程序用到了数据库。到1.1版本时,你在数据库的某个表中增加了一个字段。那么软件1.0版本用的数据库在软件1.1版本就要被升级了。


2. 数据库升级应该注意什么?


软件的1.0版本升级到1.1版本时,老的数据不能丢。那么在1.1版本的程序中就要有地方能够检测出来新的软件版本与老的数据库不兼容,并且能够有办法把1.0软件的数据库升级到1.1软件能够使用的数据库。换句话说,要在1.0软件的数据库的那个表中增加那个字段,并赋予这个字段默认值。


3. 程序如何知道数据库需要升级?


SQLiteOpenHelper类的构造函数有一个参数是int version,它的意思就是指数据库版本号。比如在软件1.0版本中,我们使用SQLiteOpenHelper访问数据库时,该参数为1,那么数据库版本号1就会写在我们的数据库中。


到了1.1版本,我们的数据库需要发生变化,那么我们1.1版本的程序中就要使用一个大于1的整数来构造SQLiteOpenHelper类,用于访问新的数据库,比如2。


当我们的1.1新程序读取1.0版本的老数据库时,就发现老数据库里存储的数据库版本是1,而我们新程序访问它时填的版本号为2,系统就知道数据库需要升级。


4. 何时触发数据库升级?如何升级?


当系统在构造SQLiteOpenHelper类的对象时,如果发现版本号不一样,就会自动调用onUpgrade函数,让你在这里对数据库进行升级。根据上述场景,在这个函数中把老版本数据库的相应表中增加字段,并给每条记录增加默认值即可。


新版本号和老版本号都会作为onUpgrade函数的参数传进来,便于开发者知道数据库应该从哪个版本升级到哪个版本。


升级完成后,数据库会自动存储最新的版本号为当前数据库版本号。



做Android应用,不可避免的会与SQLite打交道。随着应用的不断升级,原有的数据库结构可能已经不再适应新的功能,这时候,就需要对SQLite数据库的结构进行升级了。 SQLite提供了ALTER TABLE命令,允许用户重命名或添加新的字段到已有表中,但是不能从表中删除字段。

并且只能在表的末尾添加字段,比如,为 Subscription添加两个字段:

1 ALTER TABLE Subscription ADD COLUMN Activation BLOB;

2 ALTER TABLE Subscription ADD COLUMN Key BLOB;



  另外,如果遇到复杂的修改操作,比如在修改的同时,需要进行数据的转移,那么可以采取在一个事务中执行如下语句来实现修改表的需求。

  1. 将表名改为临时表

         ALTER TABLE Subscription RENAME TO __temp__Subscription;


  2. 创建新表

        CREATE TABLE Subscription (OrderId VARCHAR(32) PRIMARY KEY ,UserName VARCHAR(32) NOT NULL ,ProductId VARCHAR(16) NOT NULL);

  

      3. 导入数据  

         INSERT INTO Subscription SELECT OrderId, “”, ProductId FROM __temp__Subscription;

  或者  

        INSERT INTO Subscription() SELECT OrderId, “”, ProductId FROM __temp__Subscription;

  * 注意 双引号”” 是用来补充原来不存在的数据的

  

      4. 删除临时表  

        DROP TABLE __temp__Subscription;


  通过以上四个步骤,就可以完成旧数据库结构向新数据库结构的迁移,并且其中还可以保证数据不会应为升级而流失。

  当然,如果遇到减少字段的情况,也可以通过创建临时表的方式来实现。


Android应用程序更新的时候如果数据库修改了字段需要更新数据库,并且保留原来的数据库数据:

这是原有的数据库表

CREATE_BOOK = "create table book(bookId integer primarykey,bookName text);";

然后我们增加一个字段:

CREATE_BOOK = "create table book(bookId integer primarykey,bookName text,bookContent text);";

首先我们需要把原来的数据库表重命名一下

CREATE_TEMP_BOOK = "alter table book rename to _temp_book";

然后把备份表中的数据copy到新创建的数据库表中

INSERT_DATA = "insert into book select *,' ' from _temp_book";(注意' '是为新加的字段插入默认值的必须加上,否则就会出错)。

然后我们把备份表干掉就行啦。

DROP_BOOK = "drop table _temp_book";

然后把数据库的版本后修改一下,再次创建数据库操作对象的时候就会自动更新(注:更新的时候第一个创建的操作数据的对象必须是可写的,也就是通过这个方法getWritableDatabase()获取的数据库操作对象)

然后在onUpgrade()方法中执行上述sql语句就OK了

public class DBservice extends SQLiteOpenHelper{

    private String CREATE_BOOK = "create table book(bookId integer primarykey,bookName text);";

    private String CREATE_TEMP_BOOK = "alter table book rename to _temp_book";

    private String INSERT_DATA = "insert into book select *,'' from _temp_book";

    private String DROP_BOOK = "drop table _temp_book";

 public DBservice(Context context, String name, CursorFactory factory,int version) {

  super(context, name, factory, version);

 }

 @Override

 public void onCreate(SQLiteDatabase db) {

  db.execSQL(CREATE_BOOK);

 }

 @Override

 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

  switch (newVersion) {

  case 2:

   db.execSQL(CREATE_TEMP_BOOK);

   db.execSQL(CREATE_BOOK);

   db.execSQL(INSERT_DATA);

   db.execSQL(DROP_BOOK);

   break;

  }

 }








0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 六个月宝宝流清水鼻涕怎么办 婴儿流鼻涕怎么办最简单方法 婴儿咳嗽流鼻涕怎么办最简单方法 6个月小孩流鼻涕怎么办 宝宝风寒感冒咳嗽流鼻涕怎么办 三个月宝宝流清鼻涕怎么办 三个月宝宝留清鼻涕怎么办 三个月婴儿流清鼻涕怎么办 宝宝7个月流鼻涕怎么办 6个月孩子流鼻涕怎么办 十一个月孩子感冒流鼻涕怎么办 7个月孩子流鼻涕怎么办 18个月的宝宝流鼻涕怎么办 6个月宝宝咳嗽流鼻涕怎么办 18个月宝宝咳嗽流鼻涕怎么办 6个月宝宝流鼻涕打喷嚏怎么办 宝宝18个月流鼻涕怎么办 18个月宝宝感冒流鼻涕怎么办 小孩睡觉鼻子不通气怎么办 宝宝鼻子里有鼻涕出不来怎么办 孩子喉咙有痰呼呼响怎么办 六个月宝宝鼻塞怎么办速效办法 两个月小孩鼻子不通气怎么办 一岁宝宝流清鼻涕怎么办 孩子鼻子里有鼻涕怎么办 宝宝晚上睡觉鼻子不通气怎么办 宝宝感冒睡觉鼻子不通气怎么办 宝宝3个月流鼻涕怎么办 小孩吃着了发烧怎么办 半岁宝宝鼻子塞怎么办 宝宝伤风鼻子不通气怎么办 二十天的宝宝伤风鼻子不通怎么办 一个多月的宝宝鼻子有鼻屎怎么办 2个月宝宝鼻子里有鼻屎怎么办 四个月婴儿感冒发烧怎么办 一个月婴儿感冒发烧怎么办 五个月婴儿感冒发烧怎么办 两个月的婴儿感冒发烧怎么办 9个月婴儿感冒发烧怎么办 两个月婴儿感冒鼻塞咳嗽怎么办 两个月婴儿感冒咳嗽流鼻涕怎么办