我已经成功创建了一个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();
}
然而,虽然这种方法很有效,但只会随着问题数量的增加而变得更糟。有没有快速的方法来做这一切?
谢谢!附:理想情况下,如果行存在,它应该只更新行。因此,如果在升级中我决定删除一个问题,它应该考虑到这一点,如果该行不包含任何其他数据,则不添加新行。可能更容易让它删除没有问题数据的行而不是阻止它们被添加。
答案 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");