73 votes

La colonne Android '_id' n'existe pas?

J'ai de la difficulté avec quelque chose qui fonctionne dans le bloc-notes par exemple. Voici le code de la 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);

Ce code semble fonctionner correctement. Mais juste pour être clair, j'ai couru à la BAD utilitaire et lancez SQLite 3. J'ai inspecté le schéma comme suit:

sqlite> .schéma CRÉER une TABLE android_metadata les paramètres régionaux de TEXTE); CRÉER une TABLE des notes (_id integer primary key autoincrement, le titre du texte pas null, le corps du texte et non pas null);

Tout semble bon pour moi.


Maintenant, sur ma demande, qui, autant que je peux voir, est fondamentalement la même, avec quelques modifications mineures. J'ai simplifié et simplifié mon code, mais la problème persiste.

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

Quand je lance mon application, j'obtiens une RuntimeException et les épreuves suivantes dans le LogCat de mon Log.e() déclaration:

LogCat Message:

java.lang.IllegalArgumentException: la colonne " _id " n'existe pas

Donc, retour à SQLite 3 pour voir ce qui est différent au sujet de mon schéma:

sqlite> .schéma CRÉER une TABLE android_metadata les paramètres régionaux de TEXTE); CRÉER une TABLE des cercles (_id integer primary key autoincrement, séquence entier, rayon réel, x vraie, y vraie);

Je ne vois pas en quoi je manque le '_id'.

Qu'ai-je fait de mal?

Une chose qui est différent entre mon application et l'exemple le bloc-notes est j'ai commencé par créer mon application à partir de zéro en utilisant l' Eclipse assistant tandis que l'exemple d'application est livré déjà assemblé. Est il y a une sorte de changement environnemental j'ai besoin de faire une nouvelle demande pour utiliser une base de données SQLite?

153voto

user405821 Points 1080

Je vois, la documentation pour CursorAdapter états:

Le Curseur doit inclure une colonne nommée _id ou de cette classe ne travail.

L' SimpleCursorAdapter est une classe dérivée, donc il semble que cette déclaration s'applique. Cependant, la déclaration est techniquement faux et trompeur pour un débutant. Le jeu de résultats pour le curseur doit contenir _id, pas le curseur lui-même.
Je suis sûr que c'est clair pour un DBA parce que qui sorte de raccourci de la documentation est clair pour eux, mais pour les débutants, étant incomplète dans la déclaration des causes de la confusion. Les curseurs sont comme des itérateurs ou des pointeurs, ils ne contiennent rien, mais un mécanisme pour transversing les données, ils ne contiennent pas de colonnes elles-mêmes.

Les Chargeurs de la documentation contient un exemple de cas où il peut être vu que l' _id est inclus dans la projection de paramètre.

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

105voto

Tim Wu Points 1038

Cela a été répondu et je voudrais la rendre plus complète ici.

SimpleCursorAdapter exige que le Curseur du jeu de résultats doit inclure une colonne nommée exactement "_id". Ne pas hâte de changer de schéma si vous n'avez pas de définir le "_id" de la colonne de votre tableau. SQLite automatiquement ajouté une colonne masquée appelé "rowid" pour chaque table. Tout ce que vous devez faire est qu'il suffit de sélectionner rowid explicitement et alias '_id' Ex.

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

20voto

Deepzz Points 2890

Le code de Tim Wu fonctionne vraiment ...

Si vous utilisez db.query, alors ce serait comme ça ...

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

7voto

RoadXY Points 76

Ce qui a résolu mon problème avec cette erreur, c'est que je n'avais pas inclus la colonne _id dans ma requête de base de données. Ajouter cela a résolu mon problème.

6voto

zmbq Points 18714

Ce n'est probablement plus pertinent, mais je viens de poser le même problème aujourd'hui. Il s'avère que les noms de colonne sont sensibles à la casse. J'avais une colonne _ID, mais Android s'attend à une colonne _id.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X