Android cursor.getColumnNames() 不包含新添加的列

标签 android sql sqlite

我使用下面的代码来测试列是否存在:

  public static boolean isColumnExists(String tableName, String columnName) {
    Cursor cursor = null;
    try {
        SQLiteDatabase db = getDatabase();
        cursor = db.rawQuery("SELECT * FROM " + tableName + " LIMIT 0", null);
        String[] cloNames = cursor.getColumnNames();
        if (cloNames != null) {
            for (String temp : cloNames) {
                if (columnName.equalsIgnoreCase(temp)) {
                    return true;
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (null != cursor && !cursor.isClosed()) {
            cursor.close();
        }
    }

    return false;
}

初始状态hello2列不存在,将列添加到数据库后,下面测试仍然提示该列不存在,第二次尝试会报duplicate错误列,这是不正确的。

    if (!isColumnExists("PositionCache", "hello2")) {
        // First try will insert column to database
        getDatabase().execSQL("alter table PositionCache add hello2 Integer default 0");
    }
    if (!isColumnExists("PositionCache", "hello2")) {
        // Second try will give and error about duplicate column of hello2
        getDatabase().execSQL("alter table PositionCache add hello2 Integer default 0");
    }

我需要知道出现这种异常现象的原因。


如果我在方法 isColumnExists 中将 SELECT * FROM 更改为 select * from 那么一切都会变得正常。

enter image description here enter image description here

最佳答案

我相信原因是 SQLite(我强烈怀疑 Cursor,更准确地说是 SDK 的 Android SQLite 方面)正在缓存数据(可能是因为底层数据永远不会从数据库中检索,因为不需要获取数据(就游标而言))。

我尝试了各种检查,包括放置断点、检查 getColumnnames 的结果,以及使该方法成为非静态的。

只要我使用 PRAGMA table_info(*table_name*); 添加替代检查,该列就会存在。

因此,我建议使用以下内容:-

public static boolean isColumnExistsOld(String tableName, String columnName) {

    Cursor csr = getDatabase().rawQuery("PRAGMA table_info(" + tableName + ")",null);
    while(csr.moveToNext()) {
        if (csr.getString(csr.getColumnIndex("name")).equalsIgnoreCase(columnName)) {
            return true;
        }
    }
    return false;
    /*
    Cursor cursor = null;
    try {
        SQLiteDatabase db = getDatabase();
        cursor = db.rawQuery("SELECT * FROM " + tableName + " LIMIT 1", null);
        cursor.moveToFirst();
        String[] cloNames = cursor.getColumnNames();
        if (cloNames != null) {
            for (String temp : cloNames) {
                if (columnName.equalsIgnoreCase(temp)) {
                    return true;
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (null != cursor && !cursor.isClosed()) {
            cursor.close();
        }
    }
    boolean rv = colfound;
    return false;
    */
}
  • 请注意您的代码已被保留但被注释掉了。

我相信评估会强制刷新缓存(即我试过了,是的,它会动态更改以包含该列)。

关于Android cursor.getColumnNames() 不包含新添加的列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52250696/

相关文章:

sql - 如何在SQL Server中获取完整年份的周数、开始日期和结束日期?

sql - T-SQL//如何将北坐标/东坐标转换为纬度/经度?

sql - 修改前序树遍历 : Selecting nodes 1 level deep

sql - 是否可以在 SQL 语句中将列从字符串转换为日期时间类型?

Android - SimpleCursorAdapter.ViewBinder - 设置背景颜色

android - 无法使用 mopub 从 admob 获取广告

java - 在运行android模拟器之前保存代码?

java - 在 Android Native App 之前获取本地存储项目

objective-c - 使用llvm编译器的sqlite3编译错误

Android 6.0(API 级别 23)中的 Android 运行时权限最佳实践