我在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数据库?
答案 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
找到。