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

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

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.


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í!


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;

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.


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.


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.

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

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.


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

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


-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

.....

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.