95 votes

Comment vérifier si une table existe dans une base de données Android SQLite ?

J'ai une application Android qui doit vérifier s'il y a déjà un enregistrement dans la base de données, et si non, traiter certaines choses et éventuellement l'insérer, et simplement lire les données de la base de données si les données existent. J'utilise une sous-classe de SQLiteOpenHelper pour créer et obtenir une instance réinscriptible de SQLiteDatabase, qui, je pensais, s'occupait automatiquement de créer la table si elle n'existait pas déjà (puisque le code pour le faire est dans la méthode onCreate(...)).

Cependant, lorsque la table n'existe PAS encore, et que la première méthode exécutée sur l'objet SQLiteDatabase que j'ai est un appel à query(...), mon logcat montre une erreur de "I/Database(26434) : sqlite returned : error code = 1, msg = no such table : appdata", et bien sûr, la table appdata n'est pas créée.

Une idée de la raison ?

Je cherche soit une méthode pour tester si la table existe (car si elle n'existe pas, les données ne sont certainement pas dedans, et je n'ai pas besoin de les lire avant d'y écrire, ce qui semble créer la table correctement), soit un moyen de s'assurer qu'elle est créée, et qu'elle est juste vide, à temps pour le premier appel à query(...).

EDIT
Cette réponse a été postée après les deux réponses ci-dessous :
Je pense que j'ai peut-être trouvé le problème. Pour une raison quelconque, j'ai décidé qu'un SQLiteOpenHelper différent était censé être créé pour chaque table, même si les deux accèdent au même fichier de base de données. Je pense que la refactorisation de ce code pour n'utiliser qu'un seul OpenHelper, et créer les deux tables à l'intérieur de son onCreate pourrait fonctionner mieux...

132voto

Nikolay DS Points 499

Essaie celle-là :

public boolean isTableExists(String tableName, boolean openDb) {
    if(openDb) {
        if(mDatabase == null || !mDatabase.isOpen()) {
            mDatabase = getReadableDatabase();
        }

        if(!mDatabase.isReadOnly()) {
            mDatabase.close();
            mDatabase = getReadableDatabase();
        }
    }

    String query = "select DISTINCT tbl_name from sqlite_master where tbl_name = '"+tableName+"'";
    try (Cursor cursor = mDatabase.rawQuery(query, null)) {
        if(cursor!=null) {
            if(cursor.getCount()>0) {
                return true;
            }
        }
        return false;
    }
}

0 votes

Merci beaucoup pour cela. Il fonctionne très bien. +1

11 votes

N'oubliez pas cursor.close();

0 votes

@Gray Je veux tous les noms de table qui sont dans la base de données, comment est-ce possible ?

55voto

chrisbtoo Points 944

Je ne connais pas l'API SQLite d'Android, mais si vous êtes capable de lui parler directement en SQL, vous pouvez le faire :

create table if not exists mytable (col1 type, col2 type);

Ce qui garantira que la table sera toujours créée et ne lancera pas d'erreur si elle existait déjà.

0 votes

C'est ainsi que je crée la table dans la méthode onCreate de la classe SQLiteOpenHelper. Sous Android, il est recommandé de laisser cette classe créer la table, car cela permet à l'application de mettre à jour sa base de données automatiquement, et c'est apparemment plus efficace en général. Malheureusement, ce bloc de code qui exécute du code semblable à celui que vous avez écrit n'est pas exécuté à temps :(

0 votes

Cela fonctionne très bien et fonctionne également avec les index, c'est-à-dire : "create index if not exists [...]".

5 votes

C'est en fait la meilleure réponse à la question posée.

13voto

robguinness Points 2829

Bien qu'il y ait déjà beaucoup de bonnes réponses à cette question, j'ai trouvé une autre solution qui me semble plus simple. Entourez votre requête d'un bloc try et du catch suivant :

catch (SQLiteException e){
    if (e.getMessage().contains("no such table")){
            Log.e(TAG, "Creating table " + TABLE_NAME + "because it doesn't exist!" );
            // create table
            // re-run query, etc.
    }
}

Ça a marché pour moi !

1 votes

Ne serait-il pas préférable de placer l'instruction Log à l'intérieur du bloc if() ? Il semble que si l'exception SQLiteException est levée pour une autre raison que "no such table", le journal indiquera que vous créez la table, alors que vous ne le faites pas.

2 votes

L'utilisation d'exceptions pour contrôler le flux est une chose dont il faut avoir honte et qu'il ne faut pas enseigner aux autres. Contrôler le message de cette manière, doublement.

0 votes

Si elles sont utilisées avec parcimonie, je ne pense pas qu'il y ait de mal à utiliser les exceptions dans des cas d'utilisation tels que celui décrit ci-dessus. En tout cas, il n'y a rien dont j'ai honte.

11voto

AndroidDebaser Points 129

C'est ce que j'ai fait :

/* open database, if doesn't exist, create it */
SQLiteDatabase mDatabase = openOrCreateDatabase("exampleDb.db", SQLiteDatabase.CREATE_IF_NECESSARY,null);

Cursor c = null;
boolean tableExists = false;
/* get cursor on it */
try
{
    c = mDatabase.query("tbl_example", null,
        null, null, null, null, null);
        tableExists = true;
}
catch (Exception e) {
    /* fail */
    Log.d(TAG, tblNameIn+" doesn't exist :(((");
}

return tableExists;

8voto

camperdave Points 505

Oui, il s'avère que la théorie de mon édition était la bonne : le problème qui empêchait la méthode onCreate de s'exécuter, était le fait que SQLiteOpenHelper doivent se référer à des bases de données, et ne pas en avoir une distincte pour chaque table. Le fait de regrouper les deux tables dans une SQLiteOpenHelper a résolu le problème.

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