Android Sqlite資料庫升級時注意事項
在app版本升級時,同時升級了Sqlite資料庫的版本號的話,如果需要保留之前的資料,需要在onUpgrade方法中做處理。這裡記錄一下在onUpgrade處理升級的時候的一些注意事項。
先看下常用的SQLiteOpenHelper的方法:
public class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context, String name, CursorFactory factory, int version) {
super(context, name, factory, version);
}
/**
* 1、在第一次開啟資料庫的時候才會走
* 2、在清除資料之後再次執行-->開啟資料庫,這個方法會走
* 3、沒有清除資料,不會走這個方法
* 4、資料庫升級的時候這個方法不會走
*/
@Override
public void onCreate(SQLiteDatabase db) {
}
/**
* 1、這個方法只有當資料庫已經存在,而且版本升高的時候,才會呼叫
* 2、第一次建立資料庫的時候,這個方法不會走
* 3、清除資料後再次執行(相當於第一次建立)這個方法也不會走
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
如果第一次的資料庫版本為1,現在升級之後版本為2,即當前app版本比上次的app版本中的資料庫的版本號高1級,也有可能是3升4, 4升5這樣的,先看下這時的處理有幾種情況要考慮:
1. 摒棄之前的表並重新建立該表
這種情況一般是資料庫中的資料可能是一些無關緊要的臨時資料,處理比較簡單粗暴,直接刪除重建,且表的結構跟之前完全一樣。不過應該很少有采用這種方式的吧。
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
case 1://這裡的數值是上次的版本,也就是針對上次的版本,本次的版本要做哪些改變
db.execSQL("DROP TABLE IF EXISTS " + TableEvent.TABLE_NAME);
db.execSQL(TableEvent.CREATE_SQL);
default:
break;
}
}
2. 在之前基礎上建立新的表
這種情況也比較簡單,主要是新版比之前的版本建立新的表,而且這個表跟之前的表沒有什麼關係。這時同時也要在onCreate中加上執行建立的sql(針對新使用者)。
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
case 1://這裡的數值是上次的版本,也就是針對上次的版本,本次的版本要做哪些改變
//這種情況需要同時在onCreate中加上執行新表的建立sql(針對新使用者)
db.execSQL(xxxxx);
default:
break;
}
}
3. 在老表基礎上新增欄位
這種情況需要修改老的表新增欄位
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
case 1://這裡的數值是上次的版本,也就是針對上次的版本,本次的版本要做哪些改變
//這種情況需要同時在onCreate中加上執行新增欄位的建立表sql(針對新使用者)
db.execSQL("ALTER TABLE TableEvent.CREATE_SQL ADD COLUMN TableEvent.xxx VARCHAR(255)");
default:
break;
}
}
4. 資料庫升級時保留老的資料並同步到新的表當中
這種情況是新表保留老表的欄位結構情況
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
case 1://這裡的數值是上次的版本,也就是針對上次的版本,本次的版本要做哪些改變
//老的表重新命名
String CREATE_TEMP_BOOK = "alter table book rename to _temp_book";
//建立新的表,表名跟原來一樣,並保留原來的欄位
String CREATE_BOOK = "create table book(bookId integer primarykey, bookName text);";
//將重新命名後的老表中的資料匯入新的表中
String INSERT_DATA = "insert into book select *,'' from _temp_book";
//刪除老表
String DROP_BOOK = "drop table _temp_book";
db.execSQL(CREATE_TEMP_BOOK);
//這句要同時放到onCreate中,針對新使用者
db.execSQL(CREATE_BOOK);
db.execSQL(INSERT_DATA);
db.execSQL(DROP_BOOK);
default:
break;
}
}
5. 新表跟以前的表字段結構完全不一樣
這種情況是新表跟以前欄位結構完全不一樣或者說有大部分的差異,跟上面第4種處理差不多,但是需要手動查詢老表的某些欄位的資料然後插入的新表的對應欄位,最後刪除老表即可。
前面幾種情況是單級升級的時候,針對上次的版本本次的版本需要做的處理,如果是跨級升級,比如使用者app很久沒有更新了,這次升級資料庫版本從1升到了3,或者2升到了6,這時需要分開處理每次的版本:
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
case 1:
db.execSQL(CREATE_TBL_CATEGORY) // 建立新表
case 2:
db.execSQL("ALTER TABLE Book ADD COLUMN category_id INTEGER"); // 增加欄位
case 3:
//同步老的資料到新的表
String CREATE_TEMP_BOOK = "alter table book rename to _temp_book";
String CREATE_BOOK = "create table book(bookId integer primarykey, bookName text);";
String INSERT_DATA = "insert into book select *,'' from _temp_book";
String DROP_BOOK = "drop table _temp_book";
db.execSQL(CREATE_TEMP_BOOK);
db.execSQL(CREATE_BOOK);
db.execSQL(INSERT_DATA);
db.execSQL(DROP_BOOK);
default:
break;
}
}
注意,這裡OnUpgrade() 方法中的 switch 語句是沒有 break 的,會一直執行到語句結束。為什麼要這麼寫想想就明白了。比如使用者手上的版本是 1,新版 App 的版本是 5,那麼就會有 4 個版本的資料庫升級,switch() 自然不能中途 break,必須執行這 4 個版本的資料庫升級語句。同時每次的case中新增的建立新表的sql程式碼不要忘了在onCreate中同時新增,因為新使用者也是要執行的。
這樣的好處是每次更新資料庫的時候只需要在onUpgrade方法的末尾加一段從上個版本升級到新版本的程式碼,易於理解和維護。但是如果版本跨級比較多,這個地方可能比較費時了,建議在可控的版本差之內強制app版本升級。
參考:
https://blog.csdn.net/xx326664162/article/details/50311717
https://www.cnblogs.com/xgjblog/p/5647803.html