Android专栏'_id'不存在?

时间:2010-07-29 04:05:09

标签: android listview sqlite

我在Notepad示例中遇到问题。 这是NotepadCodeLab / Notepadv1Solution中的代码:

String[] from = new String[] { NotesDbAdapter.KEY_TITLE };
int[] to = new int[] { R.id.text1 };

SimpleCursorAdapter notes = new SimpleCursorAdapter(this,
R.layout.notes_row, c, from, to);

此代码似乎工作正常。但为了清楚起见,我跑了ADB 实用程序并运行SQLite 3.我按如下方式检查了模式:

源码> .schema

CREATE TABLE android_metadata (locale TEXT);
CREATE TABLE notes (_id integer primary key autoincrement, title text
not null, body text not null);

一切对我来说都很好。


现在我的应用程序,据我所知,它基本上是相同的 一些小的改变。我简化并简化了我的代码,但是 问题仍然存在。

String[] from = new String[] { "x" };
int[] to = new int[] { R.id.x };

SimpleCursorAdapter adapter = null;
try
{
    adapter = new SimpleCursorAdapter(this, R.layout.circle_row, cursor, from, to);
}
catch (RuntimeException e)
{
    Log.e("Circle", e.toString(), e);
}

当我运行我的应用程序时,我得到一个RuntimeException并打印以下内容 在我的Log.e()声明的LogCat中:

LogCat消息:

  

java.lang.IllegalArgumentException:列'_id'不存在

所以,回到SQLite 3,看看我的架构有什么不同:

源码> .schema CREATE TABLE android_metadata(locale TEXT); CREATE TABLE圆圈(_id整数主键自动增量,序列 整数,半径实数,x实数,y实数);

我看不出我错过了'_id'。

我做错了什么?

我的应用程序和记事本示例之间有一点不同 我开始使用的创建我的应用程序 示例应用程序已经放在一起的Eclipse向导。是 我需要为新的应用程序做一些环境变化 使用SQLite数据库?

8 个答案:

答案 0 :(得分:149)

我知道,documentation for CursorAdapter州:

  

Cursor必须包含一个名为_id的列,否则该类不会   工作

SimpleCursorAdapter是派生类,因此该语句似乎适用。然而,该声明在技术上是错误的,并且对新手有些误导。光标的结果集必须包含_id,而不是光标本身 我确信这对DBA来说是清楚的,因为那种速记文档对他们来说是清楚的,但对于那些新手来说,在声明中不完整会引起混淆。游标就像迭代器或指针一样,它们只包含一个用于遍历数据的机制,它们本身不包含任何列。

Loaders documentation包含一个示例,其中可以看到_id包含在投影参数中。

static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
    Contacts._ID,
    Contacts.DISPLAY_NAME,
    Contacts.CONTACT_STATUS,
    Contacts.CONTACT_PRESENCE,
    Contacts.PHOTO_ID,
    Contacts.LOOKUP_KEY,
};
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    // ...
    return new CursorLoader(getActivity(), baseUri,
            CONTACTS_SUMMARY_PROJECTION, select, null,
            Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
}

答案 1 :(得分:103)

这是answered,我想在这里更全面。

SimpleCursorAdapter要求Cursor的结果集必须包含一个名为“_id”的列。如果未在表中定义“_id”列,请不要急于更改架构。 SQLite为每个表自动添加了一个名为“rowid”的隐藏列。您需要做的就是明确选择rowid并将其别名为“_id”Ex。

SQLiteDatabase db = mHelper.getReadableDatabase();      
Cursor cur =  db.rawQuery( "select rowid _id,* from your_table", null);

答案 2 :(得分:20)

蒂姆吴的代码确实有用......

如果你正在使用db.query,那就像这样...

db.query(TABLE_USER, new String[] { 
                "rowid _id",
                FIELD_USERNAME,
                }, 
                FIELD_USERNAME + "=" + name, 
                null, 
                null, 
                null, 
                null);

答案 3 :(得分:7)

是的,我还更改了SELECT字符串查询以解决此问题。

String query = "SELECT t.*,t.id as _id FROM table t "; 

答案 4 :(得分:7)

解决了这个错误的问题是我没有在数据库查询中包含_id列。添加它解决了我的问题。

答案 5 :(得分:6)

这可能不再相关,但我今天遇到了同样的问题。结果列名称区分大小写。我有一个_ID列,但Android需要一个_id列。

答案 6 :(得分:0)

如果您阅读sqlite上的文档,那么创建INTEGER PRIMARY KEY类型的任何列将在内部为ROWID设置别名,因此在每个SELECT中添加别名都是不值得的,这与可能利用的任何常用实用程序不同类似于定义表的列的枚举。

http://www.sqlite.org/autoinc.html

使用它作为ROWID而不是AUTOINCREMENT选项也更直接,这可能导致_ID可能偏离ROWID。通过将_ID绑定到ROWID,意味着从insert / insertOrThrow返回主键;如果您正在编写ContentProvider,则可以在返回的Uri中使用此密钥。

答案 7 :(得分:0)

处理表中缺少_id列的另一种方法是编写CursorWrapper的子类,如果需要,可以添加一个_id列。

这样做的好处是不需要对表或查询进行任何更改。

我写了这样一个课程,如果感兴趣的话可以在https://github.com/cmgharris/WithIdCursorWrapper

找到。