Android SQLite升级而不会丢失数据

我已经成功创build了一个SQLite数据库,它工作正常。 但是,当onUpgrade方法被调用,我想这样做,而不会丢失数据。 我正在开发的应用程序是一个测验应用程序。 简单地说,当onCreate方法被调用时,我用问题,答案等来创build和预填充数据库。最后一列是他们是否将问题设置为最喜欢的。 我想要做的是,当onUpgrade方法被调用时,我想暂时保存那一列,放下整个数据库,用我对旧问题所做的任何编辑来重新创build它,然后添加新的问题,然后重新加回他们设定为最爱的问题。

所以我尝试的一个选项是:

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只是添加新的行而不是replace现有的行。 我也尝试了REPLACE INTO,INSERT OR REPLACE 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(); } 

然而,虽然这个工作非常缓慢,只会随着问题数量的增加而变得更糟。 有没有快速的方法来做到这一点?

谢谢! PS理想情况下,它应该只更新该行,如果该行存在。 因此,如果在升级中我决定删除一个问题,那么应该考虑到这个问题,如果该行不包含任何其他数据,则不要添加新行。 让它去除没有问题数据的行而不是阻止它们被添加可能会更容易。

Solutions Collecting From Web of "Android SQLite升级而不会丢失数据"

将其更改为:

 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

例如,在升级数据库模式时,谁还不知道如何升级SQLite的版本,请使用方法needUpgrade(int newVersion)!

我的代码:

 @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){ if(newVersion>oldVersion){ db.execSQL(scriptUpdate); db.needUpgrade(newVersion); } } 
 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); } } 

我没有看到你的测验表模式,但我认为它有像“问题”,“答案”,“collections夹”,以及某种独特的主键来标识每个问题,我只是叫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"); 

这将仅更新与旧测验表相匹配的新测验表的行,并从旧测验表中设置collections夹值。

我假设你有一些独特的标识符来标识每个问题,所以不是上面的rowId,而是使用那个(问题编号或者其他)。

 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); }