2012-07-05

Android 手機資料庫(三) - SQLite之資料庫更新(onUpgrade)操作

大家都知道當程式開始使用後,難免會因為修改或新增功能去修改資料庫

比如要加個功能,所以資料庫內要新增欄位,這時應該怎麼做呢?

網路上的資訊其實很少,一般都只會寫把舊的刪除

db.execSQL("DROP TABLE IF EXISTS newMemorandum"); //刪除舊有的資料表

但這樣寫使用者是會氣死的,因為資料全清空,一切重key

所以寫這個出來希望對有需要的人有幫助

該有的認知:

1.手機應用程式因為是單一封裝個體,所以資料庫也是各個獨立的
而且有版本之分,用意是用來判斷資料庫是否有修改


2.如果你只變更資料庫欄位(增加或減少),而沒有去修改版號(1 -> 2)
此時載入資料庫就會出錯,而且是要增加1號,這點要注意

實作增加欄位:
步驟1:
 private static final int VERSION = 2;//資料庫版本由1改為2  


步驟2:
新增onCreate裡面的table欄位
  //輔助類建立時運行該方法
    @Override
    public void onCreate(SQLiteDatabase db) {
    String DATABASE_CREATE_TABLE =
           "create table newMemorandum("
  + "_ID INTEGER PRIMARY KEY  AUTOINCREMENT  NOT NULL,"
         + "date VARCHAR,"
         + "note VARCHAR,"
         + "pw VARCHAR,"
         + "reminder INT,"//新增欄位
         + "type VARCHAR,"//新增欄位
         + "memo VARCHAR"//新增欄位
         + ")";
        db.execSQL(DATABASE_CREATE_TABLE);
 }

步驟3:
修改onUpgrade
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  //oldVersion=舊的資料庫版本;newVersion=新的資料庫版本

  if (newVersion > oldVersion) {
   db.beginTransaction();//建立交易
    
    boolean success = false;//判斷參數
       
    //由之前不用的版本,可做不同的動作     
    switch (oldVersion) {
    case 1:           
      db.execSQL("ALTER TABLE newMemorandum ADD COLUMN reminder integer DEFAULT 0");
      db.execSQL("ALTER TABLE newMemorandum ADD COLUMN type VARCHAR");
      db.execSQL("ALTER TABLE newMemorandum ADD COLUMN memo VARCHAR");
      oldVersion++;
            
     success = true;
     break;
    }
               
     if (success) {
       db.setTransactionSuccessful();//正確交易才成功
      }
    db.endTransaction();
  }
  else {
    onCreate(db);
  }   
}

在載入資料庫時,程式會自動去判斷資料庫的版號
如果新的版號 > 原有資料庫版號,程式就會進入onUpgrade內
讓你做原資料庫升級的動作,不然在套用修改後的table時
會出現錯誤,一些網路上的資訊都是寫直接砍掉重練XD
db.execSQL("DROP TABLE IF EXISTS newMemorandum"); //刪除舊有的資料表
不過寫這樣的程式放上Google Play應該會被罵死吧
好了,就為你介紹到這裡,有問題請留言,謝謝。


8 則留言:

  1. 你好,想請教一下onUpgrade這些程式這些是不是在下個升級版本的App中寫入就好了呢?因為我目前發佈的App還沒有onUpgrade的動機,那這樣有沒有需要在舊的App中的onUpgrade方法中寫一些預備的程式呢?謝謝你~

    因為我真的不想DROPˊˋ

    回覆刪除
    回覆
    1. 您好!

      你原先的想法是對的

      onUpgrade的使用時機是當你的APP內資料庫有修改時調用

      也就是說新的App要用來修改舊App內資料庫用

      所以舊App是不需要使用的

      刪除
    2. 謝謝,你寫的很詳細。

      刪除
  2. 如果 要做的不是新增欄位 而是新增TABLE時 該怎麼做呢?

    而且為何建立TABLE時 不用beginTransaction()/setTransactionSuccessful()/endTransaction()

    UpDate時確要呢?



    我是SQL外行人 所以有此一問

    回覆刪除
    回覆
    1. 你好:

      要新增Table在步驟三的db.execSQL中用步驟二的那段SQL指令就可以了(不了解請去看一下SQL指令)

      為何建立TABLE不用Transaction呢?因為只有一段db.execSQL,要Transaction做什麼

      那為何UpDate時要呢?因為有三段db.execSQL,一段db.execSQL表示執行一次SQL指令

      如果有三段db.execSQL不用Transaction,那在第二段出錯時,第一段已經執行了

      這是為了確保三段都正確了才一起執行,Transaction(交易)就是要麻就一起過,要麻就一起不過

      這樣清楚了嗎

      Jim

      刪除
  3. Hi, Lin :

    在更新問題上我有點小問題,

    假設我們今天資料庫是放在assets資料夾內,並且在執行程式的時候複製於程式資料夾內,

    將資料庫在外部事先建立完成,因此若要使用這個資料庫就得複製,也是方便的方法。

    但是在往後的版本更新就有點困擾,使用端也有屬於他的資料,在更新的時後恐怕會覆蓋掉原有資料,

    那麼也適用於 onUpgrade 的用法嗎?

    回覆刪除
    回覆
    1. 適用,因為原則還是不變,只會有一個資料庫檔案

      刪除
  4. 有個小問題if (newVersion > oldVersion) 應該是要改while
    不然只會更新一個版本就停了,對吧

    回覆刪除

您的寶貴建議是我前進的動力!