Android 数据库陌生列表列

发布于 2024-11-02 13:05:24 字数 2142 浏览 0 评论 0原文

我在读取 Android SQLite 数据库中的列的两种方法之间得到不一致的结果。

首先,这是根据此处接受的答案的数据库升级例程的一部分: 将 SQLite 数据库从一个版本升级到另一个版本?

该技术涉及使用临时名称移走当前表,使用新架构创建一个新表,然后将相关数据从旧表复制到新表中删除旧的临时表。

我遇到的具体问题是当我从架构中删除列时。因此,旧版本的表中存在特定列,但新版本中不存在。

该答案建议使用这样的方法来列出表中的列:

/**
 * 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);

不同结果的原因是什么?

I am getting inconsistent results between two methods of reading the columns in an Android SQLite database.

First, this is part of a database upgrade routine as per the accepted answer here: Upgrade SQLite database from one version to another?

The technique involves moving the current table away with a temporary name, creating a new table with the new schema, and then copying relevant data from the old table into the new one before deleting the old temporary table.

The particular problem I have is when I remove a column from the schema. So, a particular column exists in the old version of the table, but not the new one.

That answer suggests using a method like this to list the columns in the table:

/**
 * 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;
}

That works fine on the old table, before I move it away with a temporary name and replace it. When I run the same query again later, on the newly-created empty table, it still lists the old table schema with the name of the column which no longer exists. It looks as if it's reusing stale cached results for that query.

If I read the columns a different way, using this instead, then it returns the new column list as expected:

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();
}

The complete sequence is:

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);

What's the reason for the different results?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

温柔嚣张 2024-11-09 13:05:24

我假设您已经做过类似的事情:

ALTER TABLE "main"."mytable" RENAME TO "newtable"; 
CREATE TABLE "main"."mytable" ("key1" text PRIMARY KEY,"key2" text,"key3" text);
INSERT INTO "main"."mytable" SELECT "key1","key2","key3" FROM "main"."newtable"; 
DROP TABLE "main"."newtable";

如果有,请分享等效的代码,只是为了排除这部分的任何错误。

I assume you have done something similar to this:

ALTER TABLE "main"."mytable" RENAME TO "newtable"; 
CREATE TABLE "main"."mytable" ("key1" text PRIMARY KEY,"key2" text,"key3" text);
INSERT INTO "main"."mytable" SELECT "key1","key2","key3" FROM "main"."newtable"; 
DROP TABLE "main"."newtable";

If you have, please share the equivalent code, just to rule out any errors with this part.

盛夏已如深秋| 2024-11-09 13:05:24

我一直没有弄清楚这件事的真相。我刚刚最终使用了我提到的第二种方法,它没有出现问题。

I never got to the bottom of this. I just ended up using the second method I mentioned, which doesn't exhibit the problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文