在更新应用程序时,用户升级到新版本的本地SQLite数据库时,我遇到了不一致,不可重现的崩溃。
Fatal Exception: android.database.sqlite.SQLiteException: duplicate column name: upload_pending (code 1): , while compiling: ALTER TABLE purchases ADD COLUMN upload_pending TINYINT DEFAULT 0
#################################################################
Error Code : 1 (SQLITE_ERROR)
Caused By : SQL(query) error or missing database.
(duplicate column name: upload_pending (code 1): , while compiling: ALTER TABLE purchases ADD COLUMN upload_pending TINYINT DEFAULT 0)
#################################################################
这个版本的应用程序是新版本,它告诉我最可能的错误是SQLiteOpenHelper的onUpgrade方法被调用两次。以下是处理升级的逻辑:
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
for(int currentUpgrade = oldVersion + 1; currentUpgrade <= newVersion; currentUpgrade++) {
switch(currentUpgrade) {
case 2:
//upgrade to db v2
break;
case 3:
//upgrade to db v3
break;
//etc
case 7:
methodWhichUpdatesAnotherTable(db);
db.execSQL("ALTER TABLE " + Purchases.TABLE_NAME
+ " ADD COLUMN " + Purchases.UPLOAD_PENDING + " TINYINT DEFAULT 0");
break;
}
}
}
编辑:我已更新代码以包含重要内容。失败的行不是升级中的第一个ALTER语句。首先,调用一个方法,它生成两个不同的alter语句(在不同的表上),这部分工作正常。这似乎消除了它是并发问题的可能性,因为如果是这样的话,这将是第一个失败的。
看看这个,我能看到这种情况发生的唯一方法就是Android是两次调用升级,而不调整oldVersion
和newVersion
参数,导致案例7被调用两次。相反,可能是调用onCreate的情况,之后调用onUpgrade,同样提供给该方法的数据库版本不正确。
正如我在开始时所提到的,我无法重现此错误,并且只发生在<1%的用户身上,但对我来说,想要解决它是显而易见的。如果有人猜测我会很感激,如果您需要更多信息,请随时提出。谢谢!
答案 0 :(得分:2)
有同样的问题。原来,我在4之前为oldVersions创建了表,并为10之前的版本添加了列。因此,对于oldVersions pre 4执行了两个语句CREATE TABLE和ALTER TABLE ADD COLUM:
if ( oldVersion < 4 && newVersion >= 4 ) {
TestTableDao.createTable( db, true );
}
if ( oldVersion < 10 && newVersion >= 10 ) {
db.execSQL( "ALTER TABLE TEXT_TABLE ADD COLUMN NEW_COLUMN TEXT" );
}
修复是在创建表后检查oldVersion:
if ( oldVersion < 10 && newVersion >= 10 ) {
if( oldVersion >=4 )
db.execSQL( "ALTER TABLE TEXT_TABLE ADD COLUMN NEW_COLUMN TEXT" );
}
希望对某人有所帮助。