【问题标题】:Android cursor.getColumnNames() doesn't contain the new added columnAndroid cursor.getColumnNames() 不包含新添加的列
【发布时间】:2018-09-10 03:28:48
【问题描述】:

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

  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列初始状态不存在,将列添加到数据库后,下面的测试仍然告诉该列不存在,第二次尝试会导致重复列的错误,不是正确。

    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,那么一切都会变得正常。

【问题讨论】:

    标签: android sql sqlite


    【解决方案1】:

    我相信原因是 SQLite(我强烈怀疑游标,所以更准确地说是 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;
        */
    }
    
    • 请注意,您的代码已保留但已被注释掉。

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

    【讨论】:

    • 是的,后来我尝试了更多的测试,得出的结论和你的一样,sqlite已经缓存了命令。
    猜你喜欢
    • 1970-01-01
    • 2014-10-16
    • 1970-01-01
    • 2021-12-29
    • 1970-01-01
    • 2013-12-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多