我在读取 Android SQLite 数据库中的列的两种方法之间得到不一致的结果。
首先,这是根据此处接受的答案的数据库升级例程的一部分:将 SQLite 数据库从一个版本升级到另一版本? https://stackoverflow.com/questions/3424156/upgrade-sqlite-database-from-one-version-to-another
该技术涉及使用临时名称移走当前表,使用新架构创建一个新表,然后在删除旧临时表之前将相关数据从旧表复制到新表中。
我遇到的具体问题是当我从架构中删除列时。因此,旧版本的表中存在特定列,但新版本中不存在。
该答案建议使用这样的方法来列出表中的列:
/**
* Returns a list of the table's column names.
*/
private List<String> getColumns(SQLiteDatabase db, final String tableName) {
List<String> ar = null;
Cursor c = null;
try {
c = db.rawQuery("SELECT * FROM " + tableName + " LIMIT 1", null);
if (c != null) {
ar = new ArrayList<String>(Arrays.asList(c.getColumnNames()));
}
} finally {
if (c != null)
c.close();
}
return ar;
}
在我用临时名称将其移走并替换之前,这在旧表上运行得很好。当我稍后在新创建的空表上再次运行相同的查询时,它仍然列出旧表模式以及不再存在的列的名称。看起来好像它正在为该查询重用过时的缓存结果。
如果我以不同的方式读取列,改用它,那么它会按预期返回新的列列表:
private void listColumns(SQLiteDatabase db, final String tableName) {
final String query = "PRAGMA table_info(" + tableName + ");";
Cursor c = db.rawQuery(query, null);
while (c.moveToNext()) {
Log.v("MyApp", "Column: " + c.getString(1));
}
c.close();
}
完整的顺序是:
final String tempTableName = "temp_" + tableName;
table.addToDb(db); // ensure it exists to start with
// get column names of existing table
final List<String> columns = getColumns(db, tableName);
// backup table
db.execSQL("ALTER TABLE " + tableName + " RENAME TO " + tempTableName);
// create new table
table.addToDb(db);
// delete old columns which aren't in the new schema
columns.retainAll(getColumns(db, tableName));
// restore data from old into new table
String columnList = TextUtils.join(",", columns);
db.execSQL(String.format("INSERT INTO %s (%s) SELECT %s from %s", tableName, columnList, columnList,
tempTableName));
// remove backup
db.execSQL(DROP_TABLE + tempTableName);
结果不同的原因是什么?