SQLite数据库创建的表有2列,但错误只显示表中的一列

时间:2018-01-04 19:18:19

标签: android sqlite

以下是我要创建的表的结构:

    private static final int DATABASE_VERSION = 1;
    private static final String DATABASE_NAME = "WidgetDatabase.db";
    private static final String TABLE_WIDGET = "widgets";

    private static final String KEY_CITY = "city";
    private static final String KEY_ID = "widgetid";

    public WidgetPrefs(Context context) {
        super(context , DATABASE_NAME , null , DATABASE_VERSION);
    }


    @Override
    public void onCreate(SQLiteDatabase db) {
        String CREATE_QUESTION_TABLE = "CREATE TABLE " + TABLE_WIDGET + " (" +
                KEY_CITY + " TEXT," +
                KEY_ID + " INTEGER," +
                "PRIMARY KEY(" + KEY_ID  + ")" +
                ");";
        db.execSQL(CREATE_QUESTION_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_WIDGET);

        // Create tables again
        onCreate(db);
    }

现在,当我尝试运行这样的函数时:

public String getCity(int widgetId) {
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.rawQuery("SELECT " + KEY_CITY + " FROM " + TABLE_WIDGET + ";", null);

        if (cursor != null) {
            cursor.moveToFirst();
            if (cursor.moveToFirst()) {
                do {
                    if (widgetId == cursor.getInt(1)) {
                        Log.i("City", cursor.getString(0));
                        return cursor.getString(0);
                    }
                }
                while (cursor.moveToNext());
            }
        }
        cursor.close();
        return null;
    }

我在logcat中遇到Failed to read row 0, column 1 from a CursorWindow which has 1 rows, 1 columns.

的错误

我可以添加到此表(我可以确认,请查看下面的图片)

`Caused by: java.lang.IllegalStateException: Couldn't read row 0, col 1 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.`

Table Contents 2 columns present

3 个答案:

答案 0 :(得分:1)

你的问题是......你只选择一列...... KEY_CITY

SELECT" + KEY_CITY +"来自" + TABLE_WIDGET +&#34 ;;"

因此,您的查询结果只有一列

答案 1 :(得分:1)

如消息所示,光标有1行1列。列偏移从0开始。因此将列1指定为偏移将失败。

由于查询中只包含1列城市,因此widgetId == cursor.getInt(1)不起作用,因为没有第1列,只有第0列。

或许更改查询以包含 widgetID 列,如下所示: -

Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_WIDGET + ";", null);

在这种情况下,表中的所有列都将包含在游标中。

您拥有的代码可以简化为: -

    String rv;
    if (while cursor.moveToNext) {
        if (widgetId == cursor.getInt(1)) {
            rv = cursor.getString(0);
            cursor.close();
            return rv;
    }
    cursor.close();
    return null;

推理: -

  • 从生成游标的SQLite方法返回时,Cursor永远不会为null,因此检查null是无用的。光标将存在,尽管它可能是空的。

  • 所有光标移动????如果无法移动,方法将返回false。因此,如果光标无法移动到下一个并且不会输入while循环,while(cursor.moveToNext)将返回false。这样可以处理空光标,因此不需要使用moveToFirst进行检查。

  • 完成后,您应始终隐藏光标。 return cursor.getString(0);不会关闭光标。因此引入变量rv来保存从光标中提取的值,从而允许在返回之前关闭光标。

另一种方法是在查询中使用 WHERE 子句来选择相应的行。

这可能是

    "SELECT * FROM " + TABLE_WIDGET + " WHERE " + KEY_ID + "=" + Integer.toString(widgetId); 

最好在应用SQLite方便时使用它们,因此,许多人认为rawQuery方法不是使用query,而是更好的做法。这将构建SQL并执行它。

因此,您的getCity方法可能是: -

public String getCity(long widgetId) {
    String rv;
    SQLiteDatabase db = this.getReadableDatabase();
    Cursor cursor = db.query(
                        TABLE_WIDGET, //Table to extract cursor from
                        null, // Columns, null = all columns
                        KEY_ID + "=?", // Where clause, ? indicates an arg
                        new String[]{Long.toString(widgetId)}, //args
                        null,
                        null,
                        null);
    if (cursor.moveToFirst()) {
        rv = cursor.getString(cursor.getColumnIndex(KEY_CITY));
    }
    cursor.close();
    return rv;
}

备注

  • 理想情况下,您应该使用long而不是int来获取 id 列。这是因为rowid(您的id列为别名)可以达到高达9223372036854775807的值。SQLite Autoincrement

  • 无需循环返回的游标,因为您知道它将返回空游标或带有1行的游标。

  • 此处query更详细地解释了query方法。有4种方法具有不同的签名。

  • args(第4个参数),一个String数组,将替换where子句(第3个参数)中的?' s。数组中元素的数量应与?的数量相匹配。它们按顺序使用,即第一个?将被第一个元素,第二个元素取代的值取代?来自第二个元素的值等。

答案 2 :(得分:1)

我运行了你的代码,问题在于

Cursor cursor = db.rawQuery("SELECT " + KEY_CITY + " FROM " + TABLE_WIDGET + ";", null);

您的表格有两列,您只需选择KEY_CITY列。使用以下代码更新它

Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_WIDGET + ";", null);