Android SQLite 游标 getType 似乎正在崩溃应用程序

Android SQLite cursor getType appears to be crashing app

向我的 table 中的所有列插入临时值时,它似乎有效。请参阅下面的方法并在下面记录。但是当我用下面的测试方法测试该列是否存在时,returns该列存在是错误的!!

您还可以在日志中看到,对于除名称列之外的列,getType 返回 0??!!为此,我在底部添加了 table 创建方法(并且,是的,我更新了版本号)

请注意,此问题已根据以下评论进行编辑(因此前几条评论可能没有意义)。

第一段代码来自调用下面两个方法的地方

ContentValues values = setContVal_All_Columns(myTable);

//create row
long insertId = database.insert(myTable, null, values);
System.out.println("Column date exists = " + String.valueOf(doesColumnExist(myTable,"date")));

setContVal_All_Columns方法:

//sets generic content values to initialize row = excluding ID column
private ContentValues setContVal_All_Columns(String myTable) {

    ContentValues contentValues = new ContentValues();
    Cursor cursor = database.query(myTable,null,null,null,null,null,null);
    String[] columnNames = cursor.getColumnNames();
    cursor.moveToFirst();

    for(String name : columnNames) {
        if(!name.equals(IdColumn)) {  //excludes Id column
            int index = cursor.getColumnIndex(name);
            System.out.println("Column name = " + name + " index = " + String.valueOf(index));
            System.out.println("Type = " + String.valueOf(cursor.getType(index))); //appears to crash on the getType
            if (cursor.getType(index) == 3) {  //String
                System.out.println("Column is string");
                contentValues.put(name, " ");
            } else if (cursor.getType(index) == 1) {  //integer
                contentValues.put(name, 0);
            }
        }
    }

    return contentValues;
}

日志信息:

02-16 19:58:42.296    9711-9711/com.mycompany.dudesmyreminders I/System.out﹕ Column name = date index = 1
02-16 19:58:42.296    9711-9711/com.mycompany.dudesmyreminders I/System.out﹕ Type = 0
02-16 19:58:42.296    9711-9711/com.mycompany.dudesmyreminders I/System.out﹕ Column name = name index = 2
02-16 19:58:42.296    9711-9711/com.mycompany.dudesmyreminders I/System.out﹕ Type = 3
02-16 19:58:42.296    9711-9711/com.mycompany.dudesmyreminders I/System.out﹕ Column is string
02-16 19:58:42.296    9711-9711/com.mycompany.dudesmyreminders I/System.out﹕ Column name = altitude index = 3
02-16 19:58:42.296    9711-9711/com.mycompany.dudesmyreminders I/System.out﹕ Type = 0
02-16 19:58:42.296    9711-9711/com.mycompany.dudesmyreminders I/System.out﹕ Column name = is_used index = 4
02-16 19:58:42.296    9711-9711/com.mycompany.dudesmyreminders I/System.out﹕ Type = 0
02-16 19:58:42.296    9711-9711/com.mycompany.dudesmyreminders I/System.out﹕ Column name = warning index = 5
02-16 19:58:42.296    9711-9711/com.mycompany.dudesmyreminders I/System.out﹕ Type = 0
02-16 19:58:42.296    9711-9711/com.mycompany.dudesmyreminders I/System.out﹕ Column name = action index = 6
02-16 19:58:42.296    9711-9711/com.mycompany.dudesmyreminders I/System.out﹕ Type = 0
02-16 19:58:42.316    9711-9711/com.mycompany.dudesmyreminders I/System.out﹕ Column date exists = false

编辑:测试列是否存在的方法:总是在日期列返回 -1...

private boolean doesColumnExist(String myTable, String myColumn) {
    boolean doesExist = true;

Cursor cursor = database.rawQuery("PRAGMA table_info(" + myTable + ")",null);
cursor.moveToFirst();

int value = cursor.getColumnIndex(myColumn);

if(value == -1)
{
    doesExist = false;
}
return doesExist;
}

编辑:Table 创建方法:

//Database creation sql statement
private static final String SQL_CREATE_SPECIAL_DAYS =
        "CREATE TABLE " + dbFields.TABLE_NAME_SPECIAL_DAYS + " (" +
                dbFields.COLUMN_SPECIAL_DAYS_ID + INTEGER_PRIMARY_KEY + COMMA_SEP +
                dbFields.COLUMN_SPECIAL_DAYS_DATE + TEXT_TYPE + COMMA_SEP +
                dbFields.COLUMN_SPECIAL_DAYS_NAME + TEXT_TYPE + COMMA_SEP +
                dbFields.COLUMN_SPECIAL_DAYS_ALTITUDE + INTEGER_TYPE + COMMA_SEP +
                dbFields.COLUMN_SPECIAL_DAYS_USED + INTEGER_TYPE + COMMA_SEP +
                dbFields.COLUMN_SPECIAL_DAYS_WARNING + INTEGER_TYPE + COMMA_SEP +
                dbFields.COLUMN_SPECIAL_DAYS_ACTION + INTEGER_TYPE +
                // Any other options for the CREATE command
                " )";



@Override
public void onCreate(SQLiteDatabase database) {
    database.execSQL(SQL_CREATE_SPECIAL_DAYS);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    Log.w(MySQLiteHelper.class.getName(),
            "Upgrading database from version " + oldVersion + " to "
                    + newVersion + ", which will destroy all old data");
    db.execSQL("DROP TABLE IF EXISTS " + dbFields.TABLE_NAME_SPECIAL_DAYS);
    onCreate(db);
}

从您的原始代码块查看此代码...

Cursor cursor = database.query(myTable,null,null,null,null,null,null);
String[] columnNames = cursor.getColumnNames();

...执行任何游标查询时,游标'index'(即它指向的数据集行)始终为-1。这是索引为 0 的第一行 before(这是有原因的)。但是,此时调用 getColumNames() 是合法的,因为列名在查询过程中单独编目,并且在游标的生命周期内保持不变。

然而,调用 getType() 确实需要游标“指向”(引用)数据集中的有效行。文档并不完全清楚,但推断这是一项要求...

public abstract int getType (int columnIndex) Added in API level 11

Returns data type of the given column's value. The preferred type of the column is returned but the data may be converted to other types as documented in the get-type methods such as getInt(int), getFloat(int) etc.

换句话说,除非游标引用数据集的有效行,否则不可能获得 preferred 类型。只需将光标移动到第一行(假设它在数据集中有有效数据行)就可以获取每列中实际数据的首选类型。

所以基本上只需在使用 getType() 之前添加 moveToFirst()...

Cursor cursor = database.query(myTable,null,null,null,null,null,null);
String[] columnNames = cursor.getColumnNames();
if (cursor.getCount() > 0)
    cursor.moveToFirst(); // Calls to cursor.getType() will work from now on