Android 列“_id”不存在?

在记事本的例子中,我遇到了一些问题。 下面是 NotepadCodeLab/Notepadd1Solution 的代码:

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);

这段代码看起来运行得很好,但是为了清楚起见,我运行了“ ahref =”http://android-dls.com/wiki/index.php? title = ADB“ rel =”noReferrer“ > ADB 我检查了模式如下:

模式

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 消息:

列“ _ id”不存在

因此,回到 SQLite 3,看看我的模式有什么不同:

模式 创建 TABLE android _ meta (locale TEXT) ; CREATETABLE 圆圈(_ id 整数主键自增量,序列 整数,半径实数,x 实数,y 实数) ;

我不明白我怎么会漏掉了“ _ id”。

我做错了什么?

我的应用程序和记事本示例之间的一个不同之处是 方法从头开始创建我的应用程序 示例应用程序已经组装好的 Eclipse 向导 有一些环境的改变,我需要作出一个新的申请 使用 SQLite 数据库?

61338 次浏览

我明白了,CursorAdapter 文档说:

游标必须包含名为 _id的列,否则此类将不包含该列 工作。

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

装载机文档包含一个示例,其中可以看到 _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");
}

这已经是 回答,我想在这里使它更全面。

SimpleCursorAdapter 要求游标的结果集必须包含一个名为“ _ id”的列。如果没有在表中定义“ _ id”列,不要急于更改模式。 SQLite 自动为每个表添加一个名为“ rowid”的隐藏列。您所需要做的就是显式地选择 rowid 并将其别名为’_ id’Ex。

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

是的,我还更改了 SELECT 字符串查询来修复这个问题。

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

这可能已经无关紧要了,但我今天碰到了同样的问题。原来列名是区分大小写的。我有一个 _ ID 列,但 Android 需要一个 _ ID 列。

Tim Wu 的代码真的有用..。

如果您使用的是 db.query,那么应该是这样..。

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

这个错误解决了我的问题,因为我没有在数据库查询中包含 _ id 列。加上这个就解决了我的问题。

如果您在 sqlite 上读取文档,创建任何类型的 INTEGER PRIMARY KEY 列都将在内部使用 ROWID 作为别名,因此在每个 SELECT 中添加别名是不值得的,因为它偏离了任何可能利用诸如定义表的列的枚举之类的常用实用程序。

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

使用它作为 ROWID 比使用 AUTOINCREMENT 选项更直接,因为 AUTOINCREMENT 选项可能导致 _ ID 偏离 ROWID。通过将 _ ID 绑定到 ROWID,这意味着主键是从 insert/sertOrthrow 返回的; 如果您正在编写 ContentProvider,那么可以在返回的 Uri 中使用这个键。

处理表中缺少 _ id 列的另一种方法是编写 CursorWrapper 的子类,该子类在必要时添加 _ id 列。

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

我已经写了这样一个类,如果它的任何兴趣,它可以在 https://github.com/cmgharris/WithIdCursorWrapper找到