Android-колонка «_id» не существует?

У меня проблемы с чем-то, что работает в примере с Блокнотом. Вот код из 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. Я проверил схему следующим образом:

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

Когда я запускаю свое приложение, я получаю исключение RuntimeException и следующие отпечатки в LogCat из своего Log.e() :

Сообщение LogCat:

Java.lang.IllegalArgumentException: column '_id' не существует

Итак, вернемся к SQLite 3, чтобы узнать, что отличается от моей схемы:

Sqlite> .schema CREATE TABLE android_metadata (locale TEXT); Круги CREATE TABLE (автоинкремент целочисленного первичного ключа целых чисел, целочисленное целое число, действительный радиус, x real, y real);

Я не вижу, как мне не хватает «_id».

Что я сделал не так?

Одна вещь, которая отличается от моего приложения и примера с Notepad, заключается в том, что я начал с создания моего приложения с нуля с помощью мастера Eclipse, в то время как пример приложения уже собран. Есть ли какие-то экологические изменения, которые мне нужно сделать для нового приложения для использования базы данных SQLite?

Solutions Collecting From Web of "Android-колонка «_id» не существует?"

Я вижу, документация для CursorAdapter гласит:

Курсор должен содержать столбец с именем _id или этот класс не будет работать.

SimpleCursorAdapter является производным классом, поэтому представляется, что это утверждение применяется. Однако заявление технически неверно и несколько вводит в заблуждение новичку. Набор результатов для курсора должен содержать _id , а не сам курсор.
Я уверен, что это понятно для администратора баз данных, потому что эта краткая документация им понятна, но для тех новичков, которые неполны в заявлении, вызывает путаницу. Курсоры похожи на итераторы или указатели, они не содержат ничего, кроме механизма трансверсации данных, они не содержат самих столбцов.

Документация Loaders содержит пример, где можно увидеть, что _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 требует, чтобы результирующий набор Cursor должен содержать столбец с именем «_id». Не спешите изменять схему, если вы не указали столбец «_id» в своей таблице. SQLite автоматически добавляет скрытый столбец с именем «rowid» для каждой таблицы. Все, что вам нужно сделать, это просто выбрать rowid явно и псевдоним как «_id» Ex.

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

Код Тима Ву действительно работает …

Если вы используете db.query, то это будет так …

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

То, что решило мою проблему с этой ошибкой, состояло в том, что я не включил столбец _id в мой запрос БД. Добавив это, я решил проблему.

Вероятно, это уже не актуально, но сегодня я столкнулся с одной и той же проблемой. Оказывается, имена столбцов чувствительны к регистру. У меня был столбец _ID, но Android ожидает столбец _id.

Да, я также изменяю строковый запрос SELECT, чтобы исправить эту проблему.

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

Если вы прочитали документы на sqlite, создание любого столбца типа INTEGER PRIMARY KEY будет внутренне псевдонимом ROWID, поэтому не стоит добавлять псевдоним в каждый SELECT, отклоняясь от любых общих утилит, которые могут использовать что-то вроде Перечисление столбцов, определяющих таблицу.

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

Также более просто использовать это как ROWID вместо опции AUTOINCREMENT, которая может привести к тому, что _ID может отклоняться от ROWID. При привязке _ID к ROWID это означает, что первичный ключ возвращается из insert / insertOrThrow; Если вы пишете ContentProvider, вы можете использовать этот ключ в возвращаемом Uri.

Другой способ справиться с отсутствием столбца _id в таблице – написать подкласс CursorWrapper, который при необходимости добавит столбец _id.

Это имеет то преимущество, что не требуется никаких изменений в таблицах или запросах.

Я написал такой класс, и если это интересно, его можно найти на странице https://github.com/cmgharris/WithIdCursorWrapper