9

我已经成功创建了一个 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();

}

然而,虽然这很有效,但它非常缓慢,并且随着我的问题数量的增加只会变得更糟。有没有一种快速的方法来完成这一切?

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

4

6 回答 6

4

将其更改为:

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

于 2012-10-25T18:29:39.877 回答
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);


    }
}
于 2013-12-19T08:28:07.577 回答
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。

于 2012-10-24T00:23:24.073 回答
1

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

我的代码:

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

     if(newVersion>oldVersion){

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

}
于 2014-06-12T06:31:23.197 回答
1
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);
}
于 2015-08-20T09:33:32.767 回答
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");
于 2019-02-27T14:50:05.103 回答