2012-10-23 199 views
8

我創建了一個SQLite數據庫成功,它工作正常。但是,當onUpgrade方法被調用時,我想這樣做而不會丟失數據。我正在開發的應用程序是一個測驗應用程序。簡單地說,當onCreate方法被調用時,我使用問題,答案等創建並預填充數據庫。最後一列是他們是否已將問題設置爲最喜歡的問題。我想要做的是,當onUpgrade方法被調用時,我想暫時保存那一列,刪除整個數據庫,通過對舊問題所做的任何編輯來重新創建它,然後添加任何新問題,然後重新創建 - 回到他們設定爲最愛的問題。Android SQLite升級而不丟失數據

所以一個選項我嘗試了以下內容:

db.execSQL("ALTER TABLE quiz RENAME TO temp_quiz"); 
onCreate(db); 
db.execSQL("INSERT INTO quiz (favouries) SELECT favourites FROM temp_quiz"); 
db.execSQL("DROP TABLE IF EXISTS temp_quiz"); 

然而,這並不因爲事實上INSERT INTO的工作只是增加了新的行而不是替換現有行。我也嘗試更換,插入或更換INTO和

db.execSQL("INSERT INTO quiz (_id, favouries) SELECT _id, favourites FROM temp_quiz"); 

其中沒有工作。

目前,我確實已通過更改表名稱來調用onCreate(db)方法,然後設置一個讀取每行並使用db.update()方法的遊標,如下所示:

int place = 1; 
int TOTAL_NUMBER_OF_ROWS = 500; 

while (place < TOTAL_NUMBER_OF_ROWS) { 

String[] columns = new String[] { "_id", ..........., "FAVOURITES" }; 
// not included all the middle columns 

Cursor c = db.query("temp_quiz", columns, "_id=" + place, null, null, null, null); 

c.moveToFirst(); 

String s = c.getString(10); 
// gets the value from the FAVOURITES column 


ContentValues values = new ContentValues(); 
values.put(KEY_FLAG, s); 

String where = KEY_ROWID + "=" + place; 

db.update(DATABASE_TABLE, values, where, null); 

place++; 

c.close(); 

} 

然而,這項工作非常緩慢,只會隨着問題數量的增加而變得更糟。有沒有快速的方法來做到這一點?

謝謝!附:理想情況下,如果行存在,它應該只更新行。因此,如果在升級過程中我決定刪除問題,則應考慮到這一點,如果該行不包含任何其他數據,則不要添加新行。可以更容易地刪除沒有問題數據的行,而不是阻止它們被添加。

回答

3

將其改爲:

db.execSQL("UPDATE new_quiz SET favourites = (SELECT old_quiz.favourites 
FROM old_quiz WHERE new_quiz._id = old_quiz._id) WHERE EXISTS 
(SELECT old_quiz.favourites FROM old_quiz WHERE new_quiz._id = old_quiz._id)"); 

其中一期工程:d

+2

我想你的意思是「更新new_quiz」,而不是old_quiz =) – hiBrianLee

+0

對不起,這就是我的意思。謝謝:D – AndroidPenguin

+0

@AndroidPenguin,根據您在評論中的說明修改。 –

1

我沒有看到您的測驗表模式,但我認爲它有像「問題」,「答案」,「收藏夾」,以及某種獨特的主鍵來標識每個問題的領域,我現在只需要調用rowId。

// after renaming the old table and adding the new table 
db.execSQL("UPDATE new_quiz SET new_quiz.favorites = old_quiz.favorites where new_quiz.rowId = old_quiz.rowId"); 

這將只更新與舊測驗表匹配的新測驗表的行,並從舊測驗表中設置收藏夾值。

我假設你有一些獨特的標識符來標識每個問題,所以不是上面的rowId,而是使用那個(問題編號或其他)。

+0

沒有工作:/保持適當new_quiz.favourites引發錯誤到期。然後把它改成只是最愛的地方,但它仍然不明白。最終調整你的答案與我的選擇語句,並得到它的工作:D – AndroidPenguin

+0

啊我忘了sqlite不支持加入UPDATE =( – hiBrianLee

2
public class DataHelper extends SQLiteOpenHelper { 

    private static final String dbName="dbName"; 
    private Context context; 
    private SQLiteDatabase db; 
    private final static int version = 1; 

    public static final String SurveyTbl = "CREATE TABLE SurveyTbl (SurveyId TEXT PRIMARY KEY, Idref TEXT, SurveyDate TEXT)"; 

    public DataHelper(Context context) { 

     super(context, dbName, null, version); 
     this.db = getWritableDatabase(); 
     this.context = context; 
     Log.i("", "********************DatabaseHelper(Context context)"); 
    } 



    @Override 
    public void onCreate(SQLiteDatabase db) { 

     try { 

     db.execSQL(SurveyTbl); 

     } catch (Exception e) { 
      Log.i("", "*******************onCreate"); 
     } 
    } 



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

     try { 
      db.execSQL("ALTER TABLE HandpumpSurveyTbl ADD COLUMN NalYozna TEXT"); 



     } catch (Exception e) { 
      Log.i("", ""+e); 
     } 


     onCreate(db); 


    } 
} 
+1

在onCreate和onUpdate中捕獲異常是一個壞主意,因爲這些方法的返回值用於確定是否回滾它們在 – goonerify

2

對於誰還不知道如何升級的SQLite版本升級例如數據庫模式時,使用方法needUpgrade(int newVersion)!

我的代碼:

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

    if(newVersion>oldVersion){ 

     db.execSQL(scriptUpdate); 
     db.needUpgrade(newVersion); 
    } 

} 
+3

執行的事務。ononUpgrade()總是在'newVersion'的值高於' oldVersion',所以不需要if語句。 – Saket

0
ALTER TABLE mytable ADD COLUMN mycolumn TEXT 

在你onUpgrade方法,它會是這個樣子:

@Override 
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
    String upgradeQuery = "ALTER TABLE mytable ADD COLUMN mycolumn TEXT"; 
    if (newVersion>oldVersion) 
     db.execSQL(upgradeQuery); 
} 
相關問題