zoukankan      html  css  js  c++  java
  • Android版本升级同时Sqlite数据库的升级及之前数据的保留

    做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版本升级同时Sqlite数据库的升级及之前数据的保留
    在android应用程序需要升级时,如果之前的数据库表结构发生了变化或者新添加了表,就需要对数据库进行升级,并保留原来的数据库数据。


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


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


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


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


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


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


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


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


    下面举例写出具体过程:


    如果我上一个版本的数据库表结构没发生变化,但是新增了两张表,而且之前有一张表中默认有4条数据,现在新版本默认有11条数据,那么该怎么操作呢,假设表A发生了变化,并且新建了表B、C


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

    public static final String TEMP_SQL_CREATE_TABLE_SUBSCRIBE = "alter table "
                + A + " rename to temp_A";
    原来的表结构是:




    private static final String SQL_CREATE_TABLE_SUBSCRIBE = "create table  if not exists "
                + A + "(id integer primary key autoincrement,code text not null,name text,username text)";
    2.然后把备份表temp_A中的数据copy到新创建的数据库表A中,这个表A没发生结构上的变化




    public static final String INSERT_SUBSCRIBE = "select 'insert into A (code,name,username,tablename) 


    values ('''||code||''','''||name||''',''cnki'','''||tablename||'''')'  as insertSQL from temp_A";
     


    3.此时临时表中的数据已经全部复制到了表A中,但是我之前的表A中有四条默认的数据,用户可能删了,可能又增加了新的数据,那我不管用户什么操作,我都把这4条删除掉,然后重新添加一次,这样就保证了之前的四条数据还在新的数据表中。


    这是我之前的四条数据,我先找出来:




    public static final String[] arrWhereAct = {
                "where code ='K174' and tablename = 'phonepaper'",
                "where code ='GMRB' and tablename = 'newspaper'",
                "where code ='XJSJ' and tablename = 'magazine'",
                "where code ='JTKL' and tablename = 'magazine'" };
     


    4.删除备份表




    public static final String DELETE_TEMP_SUBSCRIBE = "delete from temp_A ";
        public static final String DROP_TEMP_SUBSCRIBE = "drop table if exists temp_A";
    5.然后把数据库版本号改为比之前高的版本号,在OnUpgrade方法中执行上述语句就行,具体如下:






    @Override


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


            


            for (int j = oldVersion; j <= newVersion; j++) {


                switch (j) {


                case 2:


              //创建临时表


                    db.execSQL(TEMP_SQL_CREATE_TABLE_SUBSCRIBE);


              //执行OnCreate方法,这个方法中放的是表的初始化操作工作,比如创建新表之类的


                    onCreate(db);


              //删除之前的表里面的那4条默认的数据


                    for (int i = 0; i < arrWhereAct.length; i++) {


                        db.execSQL(DELETE_TEMP_SUBSCRIBE + arrWhereAct[i]);


                    }


                   //将临时表中的数据放入表A 


             Cursor cursor = db.rawQuery(INSERT_SUBSCRIBE, null);


                    if (cursor.moveToFirst()) {


                        do {


                            db.execSQL(cursor.getString(cursor


                                    .getColumnIndex("insertSQL")));


                        } while (cursor.moveToNext());


                    }


                    cursor.close();


              //将临时表删除掉


                    db.execSQL(DROP_TEMP_SUBSCRIBE);





                    break;






                default:


                    break;


                }


            }

        }

    为什么要在方法里写for循环,主要是考虑到夸版本升级,比如有的用户一直不升级版本,数据库版本号一直是1,而客户端最新版本其实对应的数据库版本已经是4了,那么我中途可能对数据库做了很多修改,通过这个for循环,可以迭代升级,不会发生错误。

  • 相关阅读:
    【Codeforces 349B】Color the Fence
    【Codeforces 459D】Pashmak and Parmida's problem
    【Codeforces 467C】George and Job
    【Codeforces 161D】Distance in Tree
    【Codeforces 522A】Reposts
    【Codeforces 225C】Barcode
    【Codeforces 446A】DZY Loves Sequences
    【Codeforces 429B】Working out
    【Codeforces 478C】Table Decorations
    【Codeforces 478C】Table Decorations
  • 原文地址:https://www.cnblogs.com/loonggg/p/4981801.html
Copyright © 2011-2022 走看看