2010-07-29 61 views
65

我在记事本示例中遇到了一些问题。 下面的代码从NotepadCodeLab/Notepadv1Solution:Android列'_id'不存在?

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我检查的模式如下:

sqlite的> .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); 
} 

当我运行我的应用程序,我得到了logcat的一个RuntimeException和下面的打印 从我Log.e()声明:

logcat的消息:

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

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

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

我不明白我是如何遗漏'_id'的。

我做错了什么?

有一两件事是我的应用程序和记事本实例之间的不同是 ,我开始使用Eclipse的 向导时,示例应用程序自带已经放在一起从头开始创建我的应用程序。 有一些环境变化需要我为新的应用程序 使用SQLite数据库吗?

+1

你能提供你如何创建光标更多的细节可以发现,也许你是如何打开的数据库? – EboMike 2010-07-29 04:14:34

+3

您是否从您选择的_ID列返回?检查你的光标创建。 – Pentium10 2010-07-29 08:51:14

回答

145

我看到的,documentation for CursorAdapter状态:

光标必须包括一个名为_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"); 
} 
+14

我建议将文档中的语句写成:“游标的结果集必须包含一个名为”_id“的列,否则会产生RuntimeException。这将不那么令人困惑和正确。 – user405821 2010-07-29 16:02:27

+6

@ user405821 - 谢谢你 - 这个人并没有把你的答案标记为正确 - 但是这是一个很好的补充,这是一个很好的文档记录的Android的一部分。 +1 – tpow 2010-12-11 15:55:16

+0

我在使用google sidewiki的android文档中做了一个笔记。 sidewiki对于这类事情来说是完美的,我希望更多的人将它与android文档结合使用。 http://developer.android.com/reference/android/widget/CursorAdapter.html – 2011-10-28 22:21:18

101

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

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

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

或选择ID为_id – max4ever 2012-01-19 12:35:19

+2

最佳答案我解决问题。 – Mihir 2012-04-10 11:46:48

+0

如何覆盖'getItemId'并提供我自己定义的ID?它能解决问题吗? – BornToCode 2012-06-06 09:58:09

5

是的,我也改变了SELECT字符串查询来解决这个问题。

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

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

+0

这是一个容易犯的错误;官方文档说使用_ID。 – 2013-12-26 15:49:14

19

蒂姆·吴的代码确实有效...

如果使用db.query,那么它会是这样......

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

太棒了!万分感谢。从_id乱码保存我的数据库。保存我的日子 – TryinHard 2016-09-12 17:11:36

+0

@TryinHard:不客气:-) – Deepzz 2016-09-16 06:25:19

7

什么解决我的问题,此错误是我在我的数据库查询中没有包含_id列。添加,解决了我的问题。

+0

这是所有解决方案都无法解决问题的时候。万物的最后一招。 – 2013-06-19 14:03:10

0

如果您阅读sqlite上的文档,创建任何类型的INTEGER PRIMARY KEY列将在内部使用ROWID别名,因此不值得在每个SELECT中添加别名,这与任何可能需要的常见实用程序有所不同类似于定义表格的列的枚举的优点。

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

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

0

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

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

我写了这样一类,如果它的任何利益可在https://github.com/cmgharris/WithIdCursorWrapper

相关问题