Android數據庫升級實例
做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 RENAMETO __temp__Subscription;
2. 創建新表
CREATE TABLE Subscription (OrderIdVARCHAR(32)PRIMARYKEY
,UserNameVARCHAR(32)NOTNULL ,ProductIdVARCHAR(16)NOTNULL);
3. 導入數據
INSERT INTO SubscriptionSELECT OrderId, “”, ProductIdFROM __temp__Subscription;
或者
INSERT INTO Subscription()SELECT OrderId, “”, ProductIdFROM __temp__Subscription;
* 注意 雙引號”” 是用來補充原來不存在的數據的
4. 刪除臨時表
DROP TABLE __temp__Subscription;
通過以上四個步驟,就可以完成舊數據庫結構向新數據庫結構的遷移,並且其中還可以保證數據不會應爲升級而流失。
當然,如果遇到減少字段的情況,也可以通過創建臨時表的方式來實現。
Android數據庫升級策略
一:問題產生的一般原因
版本的升級引發以往的數據結構不能滿足新的要求
新的數據表的不斷引入
小版本迭代可能會導致數據庫的頻繁變更
二:目前常用的方案
方案:
每次更新數據庫時,刪除舊的數據,重新建表
避免使用複雜的數據表,採用json或者xml存儲
對數據庫的每次變更做記錄,在升級時執行變更的記錄
分析:
可以避免數據庫變更對新版本程序的影響,但是用戶數據會被清除,可以考慮將重要的數據存儲到SharedPreference中去。
該方式避免的數據庫變更可能產生的所有問題,但是整理上的性能和內存消耗會比較大。
該方式稍微複雜,但是是比較理想的解決方案,既避免了數據被清除掉,也避免了性能和內存消耗
三:本文討論的方案
本文主要討論二中的第三種方案,進行增量式數據變更
思路:
建立配置文件,存儲數據庫版本號,每次數據庫變更的時候將該版本號+1
建立數據變更配置文件,每一行記錄一個版本的數據變更
應用啓動執行到自定義的SQLiteOpenHelper的public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 方法時,首先執行配置文件中的版本變更記錄,然後執行onCreate()方法
實現:
DBHelper構造,傳入配置文件中的數據庫版本號
private DBHelper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); }
create
public void onCreate(SQLiteDatabase db) { //這裏建庫時記得這樣就好了CREATE TABLE IF NOT EXISTS }
onUpgrade
/** * 數據庫升級時,根據配置文件中的配置信息進行升級,可以涉及到添加字段,具體升級配置在res/raw/system.properties文件中定義 */ @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { executeLocalSQL(db); onCreate(db); }
executeLocalSQL
/** * @Title: executeLocalSQL * @Description: 執行本地SQL語句 * @param 設定文件 * @return void */ private void executeLocalSQL(SQLiteDatabase db) { ArrayList<String> sqlList = getLocalSQL(); for (int i = 0, l = sqlList.size();
i < l; i++) { try { db.execSQL(sqlList.get(i)); } catch (Exception e) { Util.log(e.getMessage()); } } }
獲取本地數據變更記錄
private ArrayList<String> getLocalSQL() { ArrayList<String> result = new ArrayList<String>(); InputStream is = null; InputStreamReader reader = null; BufferedReader br = null; try { // is = Variable.appllicationContext.getResources().getAssets().open("dbchange.txt");
is = Variable.appllicationContext.getResources().openRawResource( R.raw.alter); reader = new InputStreamReader(is); br = new BufferedReader(reader); String line = null; while((line = br.readLine())
!=null){ result.add(line); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ Util.closeStream(br);
Util.closeStream(reader); Util.closeStream(is); } return result; }
本篇文章來源於 黑基網-中國最大的網絡安全站點 原文鏈接:http://www.hackbase.com/tech/2012-11-23/67008.html
SQLite有有限的ALTER TABLE支持,可以用於添加字段到表的末尾 或更改表名。如果你要對錶的結構作更復雜的修改,你需要重新創建表。你可以在一個臨時表中備份數據,撤銷舊錶,重建新表後再恢復數據。
例如,假設你有一個名爲 "t1" 的表,有名爲 "a", "b", 和 "c" 三個字段,你要刪除字段 "c" 。可按如下步驟操作:
- BEGIN TRANSACTION;
- CREATE TEMPORARY TABLE t1_backup(a,b);
- INSERT INTO t1_backup SELECT a,b FROM t1;
- DROP TABLE t1;
- CREATE TABLE t1(a,b);
- INSERT INTO t1 SELECT a,b FROM t1_backup;
- DROP TABLE t1_backup;
- COMMIT;