当前位置: 首页 > 科技观察

如何单独升级数据库版本,将原有数据迁移过去

时间:2023-03-22 12:14:49 科技观察

在我们开发的应用中,一般都会涉及到数据库。在使用数据的时候,会涉及到数据库的升级,数据的迁移,行字段的增加。比如用户自定义数据的存储,文件端点简历信息的存储,都会涉及到数据库。我们应用的第一个版本是V1.0,在迭代V1.1版本时,我们在数据库中添加了一个字段。因此,需要在V1.1版本升级V1.0数据库。V1.0版本升级到V1.1时,原数据库中的数据不能丢失,所以V1.1中必须有一个地方可以检测版本差异。并将V1.0软件的数据库升级为V1.1软件可以使用的数据库。也就是说,在V1.0软件的数据库中的那个表中应该增加那个字段,并且给这个字段赋一个默认值。如何在应用中检测到数据库需要升级?SQLiteOpenHelper类中有一个方法:publicvoidonUpgrade(SQLiteDatabasedb,intoldVersion,intnewVersion){}当我们创建一个对象时,如果传入的版本号大于之前的版本号,这个方法就会被删除调用,通过判断oldVersion和newVersion,可以决定如何升级数据库。在这个函数中,为旧版本数据库对应的表添加字段,并为每条记录添加一个默认值。新版本号和旧版本号都会作为onUpgrade函数的参数传入,方便开发者知道数据库应该从哪个版本升级到哪个版本。升级完成后,数据库会自动存储最新版本号作为当前数据库版本号。数据库升级SQLite提供了ALTERTABLE命令,允许用户对现有表重命名或添加新字段,但不能从表中删除字段。并且只能在表的末尾添加字段,例如在Orders表中添加一个字段:"ALTERTABLEOrderADDCOLUMNCountry"代码如下:publicclassOrderDBHelperextendsSQLiteOpenHelper{privatestaticfinalintDB_VERSION=1;privatestaticfinalStringDB_NAME="Test.db";publicstaticfinalStringTABLE_NAME="订单";publicOrderDBHelper(Contextcontext,intversion){super(context,DB_NAME,null,version);}@OverridepublicvoidonCreate(SQLiteDatabasedb){Stringsql="createtableifnotexists"+TABLE_NAME+"(Idintegerprimarykey,"+"CustomNametext,OrderPriceinteger)";db.execSQL(sql);}@OverridepublicvoidonUpgrade(SQLiteDatabasedb,intoldVersion,intnewVersion){Log.e("owen","DBonUpgrade");if(newVersion==2){db.execSQL("ALTERTABLE"+TABLE_NAME+"ADDCOLUMNCountry");Cursorcr=db.rawQuery("select*from"+TABLE_NAME,null);while(cr.moveToNext()){Stringname=cr.getString(cr.getColumnIndex("CustomName"));ContentValuesvalues=newContentValues();values.put("CustomName",name);values.put("Country","China");db.update(TABLE_NAME,values,"CustomName=?",newString[]{name});}cr.close();}}OrderDBHelperorderDBHelper=newOrderDBHelper(this,2);SQLiteDatabasedb=orderDBHelper.getWritableDatabase();ContentValuescontentValues=newContentValues();contentValues.put("OrderPrice",100);contentValues.put("CustomName""OwenChan");db.insert(OrderDBHelper.TABLE_NAME,null,contentValues);Log.e("owen","createfinish");Cursorcr=db.rawQuery("select*from"+OrderDBHelper.TABLE_NAME,null);while(cr.moveToNext()){Stringname=cr.getString(cr.getColumnIndex("CustomName"));Log.e("owen","name:"+name);Stringcountry=cr.getString(cr.getColumnIndex("Country"));Log.e("owen","country:"+country);}cr.close();db.close();数据库的迁移可以分成几个步骤迁移数据库1.将表名改为临时表ALTERTABLEOrderRENAMETO_Order;2.新建表CREATETABLETest(IdVARCHAR(32)PRIMARYKEY,CustomNameVARCHAR(32)NOTNULL,CountryVARCHAR(16)NOTNULL);3.导入数据INSERTINTOOrderSELECTid,"",AgeFROM_Order;4.删除临时表DROPTABLE_Order;通过以上四个步骤,就可以完成旧数据库结构到新数据库结构的迁移,并且不会因为升级而丢失数据。当然,如果遇到减少字段的情况,也可以创建一个临时表来实现。实现代码如下:@OverridepublicvoidonUpgrade(SQLiteDatabasedb,intoldVersion,intnewVersion){if(newVersion==2){charstr='"';db.beginTransaction();db.execSQL("ALTERTABLEOrderRENAMETO_Order");db.execSQL("CREATETABLEOrder(Idintegerprimarykeyautoincrement,CustomNameVARCHAR(20)NOTNULL,"+"CountryVARCHAR(32)NOTNULL,OrderPriceVARCHAR(16)NOTNULL)");db.execSQL("INSERTINTOOrderSELECTId,"+str+str+",CustomName,OrderPriceFROM_Order");db.setfulTransaction();db.endTransaction();}}多个数据库版本的升级如果我们开发的程序发布了两个版本:V1.0和V2.0,我们开发的是V3.0,版本号为1和2分别,3.在这种情况下,我们应该如何实施升级呢?用户的选择是:V1.0->V3.0DB1->2V2.0->V3.0DB2->3每个版本的数据库代表必须定义数据库。例如,V1.0数据库可能只有TableA和TableB两个表。如果V2.0需要增加一张表TableC,如果V3.0需要修改TableC,数据库结构如下:0—>TableA,TableBV1.2—>TableA,TableB,TableCV1.3—>TableA,TableB,TableC(Modify)代码如下:@OverridepublicvoidonUpgrade(SQLiteDatabasedb,intoldVersion,intnewVersion){if(1==oldVersion){Stringsql="CreatetableC....";db.execSQL(sql);oldVersion=2;}if(2==oldVersion){//modifyColdVersion=3;}}导入现有数据库:/***CreatedbyOwenChan*On2017-09-26.*/publicclassDbManager{publicstaticfinalStringPACKAGE_NAME="com.example.sql";publicstaticfinalStringDB_NAME="table.db";publicstaticfinalStringDB_PATH="/data/data/"+PACKAGE_NAME;privateContextmContext;publicDbManager(ContextmContext){this.mContext=上下文;}publicSQLiteDatabaseopenDataBase(){returnSQLiteDatabase.openOrCreateDatabase(DB_PATH+"/"+DB_NAME,null);}publicvoidimportDB(){Filefile=newFile(DB_PATH+"/"+DB_NAME);if(!file.exists()){try{FileOutputStreamout=newFileOutputStream(file);intbuffer=1024;InputStreamin=mContext.getResources().openRawResource(R.raw.xxxx);byte[]bts=newbyte[buffer];intlenght;while((lenght=in.read(bts))>0){out.write(bts,0,bts.length);}输出。close();in.close();}catch(Exceptione){e.printStackTrace();}}}}调用方式:@OverrideprotectedvoidonResume(){super.onResume();DbManagerdbManager=newDbManager(this);dbManager.importDB();SQLiteDatabasedb=dbManager.openDataBase();db.execSQL("dowhatyouwant");}