Android SQLite升级而不会丢失数据

时间:2012-10-23 23:54:42

标签: android sqlite upgrade data-loss

我已经成功创建了一个SQLite数据库,它运行正常。但是,当调用onUpgrade方法时,我希望这样做而不会丢失数据。我正在开发的应用程序是一个测验应用程序。简单地说,当调用onCreate方法时,我使用问题,答案等创建和预填充数据库。最后一列是他们是否将问题设置为收藏夹。我想要做的是,当调用onUpgrade方法时,我想暂时保存那一列,删除整个数据库,使用我对旧问题进行的任何编辑重新创建它,然后重新添加任何新问题。 - 回复他们设置为收藏的问题。

我试过的一个选项如下:

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 INTO,INSERT或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();

}

然而,虽然这种方法很有效,但只会随着问题数量的增加而变得更糟。有没有快速的方法来做这一切?

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

6 个答案:

答案 0 :(得分: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

答案 1 :(得分: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);


    }
}

答案 2 :(得分: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。

答案 3 :(得分:1)

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

我的代码:

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

     if(newVersion>oldVersion){

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

}

答案 4 :(得分: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);
}

答案 5 :(得分:0)

例如,如何使用临时表删除表并创建新表而又不丢失数据:

db.execSQL("CREATE TEMPORARY TABLE temp_table (_id INTEGER PRIMARY KEY AUTOINCREMENT, col_1 TEXT, col_2 TEXT);");
db.execSQL("INSERT INTO temp_table SELECT _id, col_1, col_2 FROM old_table");

db.execSQL("CREATE TABLE new_table (_id INTEGER PRIMARY KEY AUTOINCREMENT, col_1 TEXT, col_2 TEXT, col_3 TEXT);");
db.execSQL("INSERT INTO new_table SELECT _id, col_1, col_2, null FROM temp_table");

db.execSQL("DROP TABLE old_table");
db.execSQL("DROP TABLE temp_table");