Wie prüft man, ob eine Tabelle in einer Android SQLite-Datenbank vorhanden ist?


87

Ich habe eine Android-App, die überprüfen muss, ob bereits ein Datensatz in der Datenbank vorhanden ist. Wenn nicht, verarbeiten Sie einige Dinge und fügen Sie sie schließlich ein. Lesen Sie einfach die Daten aus der Datenbank, wenn die Daten vorhanden sind. Ich verwende eine Unterklasse von SQLiteOpenHelper, um eine wiederbeschreibbare Instanz von SQLiteDatabase zu erstellen und abzurufen, von der ich dachte, dass sie sich automatisch um die Erstellung der Tabelle kümmert, wenn sie noch nicht vorhanden ist (da sich der dazu erforderliche Code in onCreate befindet (... ) Methode).

Wenn die Tabelle jedoch noch NICHT vorhanden ist und die erste Methode, die für das SQLiteDatabase-Objekt ausgeführt wird, ein Aufruf zur Abfrage (...) ist, zeigt mein Logcat den Fehler "I / Database (26434): sqlite return: error code = 1, msg = keine solche Tabelle: appdata ", und tatsächlich wird die appdata-Tabelle nicht erstellt.

Irgendwelche Ideen warum?

Ich suche nach einer Methode, um zu testen, ob die Tabelle vorhanden ist (denn wenn dies nicht der Fall ist, sind die Daten sicherlich nicht darin enthalten, und ich muss sie erst lesen, wenn ich darauf schreibe, wodurch die Tabelle erstellt wird richtig) oder eine Möglichkeit, um sicherzustellen, dass es erstellt wird und nur leer ist, rechtzeitig für diesen ersten Aufruf zur Abfrage (...)

BEARBEITEN
Dies wurde nach den beiden folgenden Antworten gepostet:
Ich glaube, ich habe das Problem gefunden. Ich habe aus irgendeinem Grund entschieden, dass für jede Tabelle ein anderer SQLiteOpenHelper erstellt werden soll, obwohl beide auf dieselbe Datenbankdatei zugreifen. Ich denke, dass das Umgestalten dieses Codes, um nur einen OpenHelper zu verwenden, und das Erstellen beider Tabellen in onCreate möglicherweise besser funktioniert ...

Antworten:


126

Probier diese:

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

Vielen Dank dafür. Funktioniert super. +1
Grau

11
Vergiss nichtcursor.close();
styler1972

1
Aus unbekannten Gründen unterscheidet der Tabellenname zwischen Groß- und Kleinschreibung. Ich benutze lieberselect * from sqlite_master where UPPER(name) = 'ROUTES'.
Thupten

4
Schöne Antwort, aber schmerzhafte Grammatik! Sollte sicherlich 'isTableExisting ()' heißen.
Chris Hatton

1
Dies funktionierte für mich, aber ich musste die Abfrage in einen Versuch / Fang einschließen, sonst stürzte meine App ab, wenn die Tabelle nicht existierte.
Braden Holt

51

Ich weiß nichts über die Android SQLite-API, aber wenn Sie in SQL direkt mit ihr kommunizieren können, können Sie Folgendes tun:

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

Dadurch wird sichergestellt, dass die Tabelle immer erstellt wird und keine Fehler ausgelöst werden, wenn sie bereits vorhanden ist.


So erstelle ich die Tabelle in der onCreate-Methode in der SQLiteOpenHelper-Klasse. In Android wird empfohlen, diese Klasse die Tabelle erstellen zu lassen, da die App ihre Datenbank automatisch aktualisieren kann und dies im Allgemeinen anscheinend effizienter ist. Leider wird dieser Codeblock, der Code ähnlich dem von Ihnen geschriebenen ausführt, nicht rechtzeitig ausgeführt :(
camperdave

Dies funktioniert hervorragend und funktioniert auch mit Indizes, dh: "Index erstellen, wenn nicht vorhanden [...]".
Eric Fortier

5
Dies ist eigentlich die beste Antwort auf die gestellte Frage.
Das Original Android

1
aber die Frage verlangt nicht, eine zu erstellen
10101010

12

Obwohl es bereits viele gute Antworten auf diese Frage gibt, habe ich eine andere Lösung gefunden, die ich für einfacher halte. Umgeben Sie Ihre Abfrage mit einem try-Block und dem folgenden Haken:

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

Es hat bei mir funktioniert!


1
Wäre es nicht besser, die Log-Anweisung in den if () -Block zu setzen? Wenn die SQLiteException aus einem anderen Grund als "keine solche Tabelle" ausgelöst wird, zeigt das Protokoll an, dass Sie die Tabelle erstellen, während dies tatsächlich nicht der Fall ist.

2
Die Verwendung von Ausnahmen zur Steuerung des Flusses ist etwas, für das man sich schämen muss und das anderen nicht beigebracht wird. Überprüfen Sie die Nachricht auf diese Weise doppelt.
Nick Cardoso

Bei sparsamer Verwendung glaube ich nicht, dass die Verwendung von Ausnahmen in Anwendungsfällen wie dem oben beschriebenen falsch ist. Sicher nichts, wofür ich mich schäme.
Robguinness

Ich denke, es e.getMessage().contains("no such table")ist schlimmer als Ausnahmen für den Kontrollfluss zu verwenden. Beides ist ein schlechter Stil, aber das Parsen von Fehlermeldungen für bestimmten Text ist sogar ein sehr schlechter Stil.
Jox

11

Das habe ich getan:

/* 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

Ja, es stellte sich heraus, dass die Theorie in meiner Bearbeitung richtig war: Das Problem, das dazu führte, dass die onCreate-Methode nicht ausgeführt wurde, war die Tatsache, dass SQLiteOpenHelperObjekte auf Datenbanken verweisen sollten und nicht für jede Tabelle eine eigene haben sollten. Das Packen beider Tabellen in eine SQLiteOpenHelperlöste das Problem.


2

Sie haben erwähnt, dass Sie eine Klasse erstellt haben, SQLiteOpenHelperdie die onCreateMethode erweitert und implementiert . Stellen Sie sicher, dass Sie alle Ihre Datenbankerfassungsaufrufe mit dieser Klasse ausführen? Sie sollten nur SQLiteDatabaseObjekte über das erhaltenSQLiteOpenHelper#getWritableDatabase abrufen, getReadableDatabaseandernfalls wird die onCreateMethode bei Bedarf nicht aufgerufen. Wenn Sie dies bereits tun, überprüfen Sie, ob SQLiteOpenHelper#onUpgradestattdessen die Methode aufgerufen wird. Wenn ja, wurde die Versionsnummer der Datenbank zu einem bestimmten Zeitpunkt geändert, aber die Tabelle wurde zu diesem Zeitpunkt nie ordnungsgemäß erstellt.

Nebenbei können Sie die Neuerstellung der Datenbank erzwingen, indem Sie sicherstellen, dass alle Verbindungen zu ihr geschlossen sind, und aufrufen Context#deleteDatabaseund dann das verwenden SQLiteOpenHelper, um Ihnen ein neues Datenbankobjekt zu geben.


Nun, ich erhalte mein Datenbankobjekt über den Aufruf von getWritableDatabase (). Entschuldigung, ich habe vergessen, dies anzugeben. Ich bin mir auch sicher, dass onUpgrade () nicht aufgerufen wird, da diese Methode einen Log.d (...) - Aufruf als erste Zeile hat, die ich nicht in der Datenbank sehe. Ich werde versuchen, die gesamte Datenbankdatei zu löschen, und wir werden sehen, ob das irgendwie das
Problem

Leider hat das Löschen der gesamten Datenbank (ich habe den Root-Explorer zum Löschen der Datei verwendet) nicht funktioniert. Ich verwende zwei Tabellen in meiner App - eine davon ist perfekt initialisiert, die andere, die mir die ganze Zeit Probleme bereitet hat, jedoch nicht.
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 verwaltet die Tabelle sqlite_master mit Informationen zu allen Tabellen und Indizes in der Datenbank.
  • Hier führen wir einfach den Befehl SELECT aus und erhalten einen Cursor mit der Zählung 1, wenn eine Tabelle vorhanden ist.

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 kommt, weil, sobald Sie eine Datenbank mit einer Tabelle danach erstellen, wenn Sie eine Tabelle in derselben Datenbank erstellen, dieser Fehler auftritt.

Um diesen Fehler zu beheben, müssen Sie eine neue Datenbank erstellen und innerhalb der onCreate () -Methode können Sie mehrere Tabellen in derselben Datenbank erstellen.


0

Wichtige Bedingung ist, WENN NICHT EXISTIERT , um zu überprüfen, ob die Tabelle bereits vorhanden ist oder nicht in der Datenbank vorhanden ist

mögen...

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

0

Ich habe mich dem gestellt und damit umgegangen, indem ich versucht habe, so einfach zu fangen, dass ich das tue, was ich in der Tabelle will, wenn es nicht existiert, wird es Fehler verursachen, also fange es durch Ausnahmen und erstelle es :)

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 (Kontext, "try ...", 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

..... .....

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.