¿Cómo se comprueba si existe una tabla en una base de datos SQLite de Android?

87

Tengo una aplicación de Android que debe verificar si ya hay un registro en la base de datos, y si no, procesar algunas cosas y eventualmente insertarlo, y simplemente leer los datos de la base de datos si los datos existen. Estoy usando una subclase de SQLiteOpenHelper para crear y obtener una instancia regrabable de SQLiteDatabase, que pensé que automáticamente se encargaba de crear la tabla si aún no existía (ya que el código para hacer eso está en onCreate (... ) método).

Sin embargo, cuando la tabla NO existe todavía, y el primer método que se ejecutó en el objeto SQLiteDatabase que tengo es una llamada a la consulta (...), mi logcat muestra un error de "I / Database (26434): sqlite regresó: error code = 1, msg = no such table: appdata ", y efectivamente, la tabla appdata no se está creando.

¿Alguna idea de por qué?

Estoy buscando un método para probar si la tabla existe (porque si no existe, los datos ciertamente no están en ella, y no necesito leerlos hasta que escribo en ellos, lo que parece crear la tabla correctamente), o una forma de asegurarse de que se cree, y esté simplemente vacío, a tiempo para esa primera llamada para consultar (...)

EDITAR
Esto se publicó después de las dos respuestas a continuación:
Creo que he encontrado el problema. Por alguna razón, decidí que se suponía que debía crearse un SQLiteOpenHelper diferente para cada tabla, aunque ambos acceden al mismo archivo de base de datos. Creo que refactorizar ese código para usar solo un OpenHelper y crear ambas tablas dentro de su onCreate puede funcionar mejor ...

camperdave
fuente

Respuestas:

127

Prueba este:

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;
    }
}
Nikolay DS
fuente
Muchas gracias por esto Funciona genial. +1
Gray
11
No lo olvidescursor.close();
styler1972
1
Por razones desconocidas, el nombre de la tabla distingue entre mayúsculas y minúsculas. Prefiero usarselect * from sqlite_master where UPPER(name) = 'ROUTES'.
Thupten
4
¡Buena respuesta pero gramática dolorosa! Seguramente debería llamarse 'isTableExisting ()'.
Chris Hatton
1
Esto funcionó para mí, pero tuve que envolver la consulta en un intento / captura o mi aplicación se bloqueaba cuando la tabla no existía.
Braden Holt
52

No sé nada sobre la API de SQLite de Android, pero si puede hablar con ella directamente en SQL, puede hacer esto:

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

Lo que garantizará que la tabla siempre se cree y no arroje ningún error si ya existía.

chrisbtoo
fuente
Así es como estoy creando la tabla en el método onCreate dentro de la clase SQLiteOpenHelper. En Android, se recomienda dejar que esa clase cree la tabla, ya que permite que la aplicación actualice su base de datos automáticamente y aparentemente es más eficiente en general. Desafortunadamente, ese bloque de código que ejecuta un código muy parecido al que escribió no se ejecuta a tiempo :(
camperdave
Esto funciona muy bien y también funciona con índices, es decir: "crear índice si no existe [...]".
Eric Fortier
5
En realidad, esta es la mejor respuesta para la pregunta formulada.
The Original Android
1
pero la pregunta no pide crear uno
10101010
12

Aunque ya hay muchas buenas respuestas a esta pregunta, se me ocurrió otra solución que creo que es más simple. Rodee su consulta con un bloque de prueba y la siguiente captura:

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.
    }
}

¡Funcionó para mí!

robguinness
fuente
1
¿No sería mejor poner la instrucción Log dentro del bloque if ()? Parece que si la excepción SQLiteException se lanza por otra razón que "no existe tal tabla", el registro indicará que está creando la tabla, mientras que en realidad no lo está.
2
Usar excepciones para controlar el flujo es algo de lo que avergonzarse, que no se debe enseñar a los demás. Verificando el mensaje de esa manera, doblemente.
Nick Cardoso
Si se usa con moderación, no creo que haya nada de malo en usar excepciones en casos de uso como el descrito anteriormente. Ciertamente nada de lo que me avergüence.
robguinness
Creo que e.getMessage().contains("no such table")es peor que usar excepciones para controlar el flujo. Ambos son de mal estilo, pero analizar mensajes de error para un texto específico es incluso de muy mal estilo.
jox
11

Esto es lo que hice:

/* 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;
AndroidDebaser
fuente
8

Sí, resulta que la teoría en mi edición era correcta: el problema que causaba que el método onCreate no se ejecutara era el hecho de que los SQLiteOpenHelperobjetos deberían referirse a bases de datos y no tener una separada para cada tabla. Empaquetando ambas tablas en una se SQLiteOpenHelperresolvió el problema.

camperdave
fuente
2

Mencionaste que has creado una clase que amplía SQLiteOpenHelpere implementa el onCreatemétodo. ¿Se está asegurando de realizar todas las llamadas de adquisición de su base de datos con esa clase? Solo debe obtener SQLiteDatabaseobjetos a través de SQLiteOpenHelper#getWritableDatabasey, de lo getReadableDatabasecontrario onCreate, no se llamará al método cuando sea necesario. Si ya está haciendo eso, verifique si SQLiteOpenHelper#onUpgradese está llamando al método en su lugar. Si es así, el número de versión de la base de datos se cambió en algún momento, pero la tabla nunca se creó correctamente cuando eso sucedió.

Además, puede forzar la recreación de la base de datos asegurándose de que todas las conexiones a ella estén cerradas y llamando Context#deleteDatabasey luego usando SQLiteOpenHelperpara darle un nuevo objeto db.

Rich Schuler
fuente
Bueno, obtengo mi objeto de base de datos a través de la llamada getWritableDatabase (), lo siento, olvidé especificar eso. Además, estoy seguro de que no se está llamando a onUpgrade (), ya que ese método tiene una llamada Log.d (...) como primera línea que no veo en la base de datos. Intentaré eliminar todo el archivo de la base de datos y veremos si eso lo soluciona de alguna manera ...
camperdave
Desafortunadamente, eliminar toda la base de datos (utilicé el explorador raíz para purgar el archivo) no funcionó. Utilizo dos tablas en mi aplicación, una de ellas se inicializó perfectamente, pero la otra que me ha estado dando problemas todo el tiempo no lo hizo.
camperdave
2
 // @param db, readable database from SQLiteOpenHelper

 public boolean doesTableExist(SQLiteDatabase db, String tableName) {
        Cursor cursor = db.rawQuery("select DISTINCT tbl_name from sqlite_master where tbl_name = '" + tableName + "'", null);

    if (cursor != null) {
        if (cursor.getCount() > 0) {
            cursor.close();
            return true;
        }
        cursor.close();
    }
    return false;
}
  • sqlite mantiene la tabla sqlite_master que contiene información de todas las tablas e índices en la base de datos.
  • Así que aquí simplemente estamos ejecutando el comando SELECT en él, obtendremos el cursor con un conteo 1 si la tabla existe.
Akshansh singh
fuente
0
 public boolean isTableExists(String tableName) {
    boolean isExist = false;
    Cursor cursor = db.rawQuery("select DISTINCT tbl_name from sqlite_master where tbl_name = '" + tableName + "'", null);
    if (cursor != null) {
        if (cursor.getCount() > 0) {
            isExist = true;
        }
        cursor.close();
    }
    return isExist;
}
Yogesh Rathi
fuente
0

no such table exists: error viene porque una vez que crea una base de datos con una tabla después de eso, siempre que crea una tabla en la misma base de datos, aparece este error.

Para solucionar este error debes tener que crear una nueva base de datos y dentro del método onCreate () puedes crear múltiples tablas en la misma base de datos.

Megha
fuente
0

La condición importante es SI NO EXISTE comprobar que la tabla ya existe o no está en la base de datos

me gusta...

String query = "CREATE TABLE IF NOT EXISTS " + TABLE_PLAYER_PHOTO + "("
            + KEY_PLAYER_ID + " TEXT,"
            + KEY_PLAYER_IMAGE + " TEXT)";
db.execSQL(query);
Pankaj Talaviya
fuente
0

Me enfrenté a eso y lo resolví intentando capturar algo tan simple como que hago lo que quiero en la tabla, si no existe, causará un error, así que cógelo por excepciones y créalo :)

SQLiteDatabase db=this.getWritableDatabase();
        try{
            db.execSQL("INSERT INTO o_vacations SELECT * FROM vacations");
            db.execSQL("DELETE FROM vacations");
        }catch (SQLiteException e){
            db.execSQL("create table o_vacations (id integer primary key ,name text ,vacation text,date text,MONTH text)");
            db.execSQL("INSERT INTO o_vacations SELECT * FROM vacations");
            db.execSQL("DELETE FROM vacations");
        }

Aly Abdelaal
fuente
-1

..... Toast t = Toast.makeText (contexto, "probar ...", Toast.LENGTH_SHORT); t.show ();

    Cursor callInitCheck = db.rawQuery("select count(*) from call", null);

    Toast t2a = Toast.makeText(context, "count rows " + callInitCheck.getCount() , Toast.LENGTH_SHORT);
    t2a.show();

    callInitCheck.moveToNext();
    if( Integer.parseInt( callInitCheck.getString(0)) == 0) // if no rows then do
    {
        // if empty then insert into call

.....

Srinath Ganesh
fuente