Android SQLite添加列报错:CursorWindow无法读取列8问题求助
解决SQLite升级失败与Cursor访问异常问题
先拆解你遇到的两个核心问题:onUpgrade未触发和Cursor列访问报错,一步步帮你修复:
1. 为什么onUpgrade没执行?
SQLite的onUpgrade只有在代码里的数据库版本号大于本地已存在的数据库版本号时才会触发。你现在定义的DATABASE_VERSION还是1,和初始版本一致,系统根本不会认为需要升级。
先把版本号改成更高的数值,比如2(对应你第一次添加3列的升级操作):
// 把版本从1改为2,触发升级逻辑 private static final int DATABASE_VERSION = 2;
2. onUpgrade里的致命逻辑错误
你的onUpgrade开头先执行了DROP TABLE IF EXISTS,这会直接删掉原有表,之后的ALTER TABLE操作完全找不到目标表;最后还调用了onCreate(db),等于重新创建了只有8列的旧结构表,新列根本没加上。
正确的升级逻辑是保留原有表,直接添加新列(只有在旧版本完全无法兼容时才考虑删表重建)。修改后的onUpgrade应该是这样:
@Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.d(TAG, "DB Version =>" + db.getVersion()); // 按版本递进处理升级,确保低版本能逐步升级到最新版本 if (oldVersion < 2) { // 新增3列,SQL语句末尾分号可加可不加 db.execSQL("ALTER TABLE " + TABLE_CONTACTS + " ADD COLUMN " + KEY_BEXERCISE + " TEXT"); db.execSQL("ALTER TABLE " + TABLE_CONTACTS + " ADD COLUMN " + KEY_AEXERCISE + " TEXT"); db.execSQL("ALTER TABLE " + TABLE_CONTACTS + " ADD COLUMN " + KEY_COMMENT + " TEXT"); } if (oldVersion < 3) { // 后续有新的升级需求,在这里追加操作即可 } // 绝对不要在这里调用onCreate!除非你明确要彻底清空重建表 }
3. 解决Cursor访问异常
java.lang.IllegalStateException: Couldn't read row 0, col 8 from CursorWindow这个错误,是因为你的getAllContacts方法里尝试读取索引为8的列(对应新增的KEY_BEXERCISE),但旧数据库里根本没有这一列。
修复升级逻辑后,新列会被正确添加到表中,Cursor就能正常读取了。另外建议你用列名而非索引取值,避免后续表结构变化导致索引偏移:
// 不要用cursor.getString(8)这种硬编码索引的方式 String bExercise = cursor.getString(cursor.getColumnIndex(KEY_BEXERCISE));
测试验证步骤
- 卸载当前App(或在系统设置里清除App数据),彻底删除旧数据库;
- 重新运行App,此时Logcat应该能看到
DB Version的日志,说明onUpgrade已触发; - 检查数据库表结构,确认3个新列已添加,
getAllContacts也不会再报Cursor错误。
内容的提问来源于stack exchange,提问作者Morton
相关产品推荐
相关产品推荐

