web-dev-qa-db-ger.com

Wann wird SQLiteOpenHelper onCreate ()/onUpgrade () ausgeführt?

Ich habe meine Tabellen in meiner SQLiteOpenHelperonCreate() erstellt, aber erhalten

SQLiteException: no such table

oder

SQLiteException: no such column

fehler. Warum?

HINWEIS:

(Dies ist die Zusammenfassung von Dutzenden ähnlicher Fragen jede Woche. Versuch, hier eine "kanonische" Community-Wiki-Frage/Antwort bereitzustellen, damit alle diese Fragen auf eine gute Referenz verwiesen werden können.)

267
laalto

SQLiteOpenHelperonCreate() und onUpgrade() callbacks werden aufgerufen, wenn die Datenbank tatsächlich geöffnet wird, beispielsweise durch einen Aufruf an getWritableDatabase() . Die Datenbank wird nicht geöffnet, wenn das Datenbank-Hilfsobjekt selbst erstellt wird.

SQLiteOpenHelper gibt die Datenbankdateien aus. Die Versionsnummer ist das Argument int, das an den Konstruktor übergeben wird. In der Datenbankdatei ist die Versionsnummer in PRAGMA user_version gespeichert.

onCreate() wird nur ausgeführt, wenn die Datenbankdatei nicht vorhanden war und gerade erstellt wurde. Wenn onCreate() erfolgreich zurückgegeben wird (keine Ausnahme ausgelöst wird), wird davon ausgegangen, dass die Datenbank mit der angeforderten Versionsnummer erstellt wurde. Als Folge davon sollten Sie SQLExceptions in onCreate() nicht selbst einfangen.

onUpgrade() wird nur aufgerufen, wenn die Datenbankdatei vorhanden ist, die gespeicherte Versionsnummer jedoch niedriger ist als im Konstruktor angefordert. onUpgrade() sollte das Tabellenschema auf die angeforderte Version aktualisieren.

Wenn Sie das Tabellenschema im Code (onCreate()) ändern, sollten Sie sicherstellen, dass die Datenbank aktualisiert wird. Zwei Hauptansätze:

  1. Löschen Sie die alte Datenbankdatei, damit onCreate() erneut ausgeführt wird. Dies wird häufig zur Entwicklungszeit bevorzugt, wenn Sie die installierten Versionen selbst kontrollieren können und Datenverlust kein Problem darstellt. Einige Möglichkeiten zum Löschen der Datenbankdatei:

    • Deinstallieren Sie die Anwendung. Verwenden Sie den Anwendungsmanager oder adb uninstall your.package.name von Shell.

    • Anwendungsdaten löschen Verwenden Sie den Anwendungsmanager.

  2. Inkrementieren Sie die Datenbankversion, sodass onUpgrade() aufgerufen wird. Dies ist etwas komplizierter, da mehr Code benötigt wird.

    • Bei Aktualisierungen des Entwicklungszeitschemas, bei denen Datenverlust kein Problem darstellt, können Sie einfach mit execSQL("DROP TABLE IF EXISTS <tablename>") in Ihre vorhandenen Tabellen entfernen und onCreate() aufrufen, um die Datenbank neu zu erstellen.

    • Bei freigegebenen Versionen sollten Sie die Datenmigration in onUpgrade() implementieren, damit Ihre Benutzer ihre Daten nicht verlieren.

337
laalto

Um hier weiter fehlende Punkte hinzuzufügen, wie auf Anfrage von Jaskey

Die Datenbankversion wird in der Datenbankdatei SQLite gespeichert.

catch ist der Konstruktor

SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)

Wenn also der Datenbank-Hilfskonstruktor mit einer name (2nd param) aufgerufen wird, prüft die Plattform, ob die Datenbank vorhanden ist oder nicht. Wenn die Datenbank vorhanden ist, ruft sie die Versionsinformationen aus dem Kopf der Datenbankdatei ab und löst den richtigen Rückruf aus

Wie bereits in der älteren Antwort erläutert, löst die Datenbank mit dem Namen onCreate aus.

Nachfolgend wird der Fall onUpgrade anhand eines Beispiels erläutert.

Angenommen, Ihre erste Version der Anwendung hatte DatabaseHelper (Erweiterung SQLiteOpenHelper), wobei die Version des Konstruktors als 1 übergeben wurde, und Sie haben dann eine aktualisierte Anwendung mit dem neuen Quellcode bereitgestellt, deren Version als 2 übergeben wurde. Dann löst die Plattform automatisch DatabaseHelper aus, wenn die onUpgrade erstellt wird Die Datei ist bereits vorhanden, aber die Version ist niedriger als die aktuelle Version, die Sie übergeben haben.

Angenommen, Sie planen, eine dritte Version der Anwendung mit der Datenbankversion als 3 anzugeben (die Datenbankversion wird nur erhöht, wenn das Datenbankschema geändert werden soll). Bei solchen inkrementellen Aktualisierungen müssen Sie die Aktualisierungslogik für jede Version inkrementell schreiben, um einen besser wartbaren Code zu erhalten

Beispiel Pseudo-Code unten:

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  switch(oldVersion) {
    case 1:
       //upgrade logic from version 1 to 2
    case 2:
       //upgrade logic from version 2 to 3
    case 3:
       //upgrade logic from version 3 to 4
       break;
    default:
       throw new IllegalStateException(
                "onUpgrade() with unknown oldVersion " + oldVersion);
  }
}

Beachten Sie die fehlende break-Anweisung für den Fall 1 und 2. Das meine ich mit inkrementellem Upgrade.

Sagen Sie, wenn die alte Version 2 und die neue Version 4 ist, aktualisiert die Logik die Datenbank von 2 auf 3 und dann auf 4.

Wenn die alte Version 3 und die neue Version 4 ist, wird nur die Aktualisierungslogik für 3 auf 4 ausgeführt.

93
Aun

onCreate()

  1. Beim ersten Erstellen einer Datenbank (d. H. Datenbank ist nicht vorhanden) onCreate() Datenbank mit Version erstellen, die übergeben wird SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)

  2. onCreate() erstellt die Tabellen, die Sie definiert haben, und führt jeden anderen Code aus, den Sie geschrieben haben. Diese Methode wird jedoch nur aufgerufen, wenn die SQLite-Datei im Datenverzeichnis Ihrer App fehlt (/data/data/your.apps.classpath/databases). 

  3. Diese Methode wird nicht aufgerufen, wenn Sie Ihren Code geändert und im Emulator neu gestartet haben. Wenn Sie möchten, dass onCreate() ausgeführt wird, müssen Sie die SQLite-Datenbankdatei mit adb löschen.

onUpgrade()

  1. SQLiteOpenHelper sollte den Superkonstruktor aufrufen.
  2. Die Methode onUpgrade() wird nur aufgerufen, wenn die Versionsganzzahl größer ist als die aktuelle Version, die in der App ausgeführt wird.
  3. Wenn Sie möchten, dass die Methode onUpgrade() aufgerufen wird, müssen Sie die Versionsnummer in Ihrem Code erhöhen.
19
jeet parmar

Vielleicht bin ich zu spät, aber ich möchte meine kurze und süße Antwort mit Ihnen teilen. Bitte überprüfen Sie Answer für dasselbe Problem. Es wird dir definitiv helfen. Keine tiefen Spezifikationen mehr.

Wenn Sie mit der Syntax zum Erstellen von Tabellen vertraut sind, kann dies passieren, wenn Sie in derselben Tabelle eine neue Spalte hinzufügen.

1) Deinstalliere dein Gerät und führe es erneut aus.

OR

2) Einstellung -> App -> ClearData

OR

3) Ändern Sie DATABASE_VERSION in Ihrer "DatabaseHandler" -Klasse (Wenn Sie eine neue Spalte hinzugefügt haben, wird das Upgrade automatisch durchgeführt)

public DatabaseHandler(Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

OR

4) Change DATABASE_NAME in Ihrer "DatabaseHandler" -Klasse (Ich hatte das gleiche Problem. Aber ich ändere DATABASE_NAME.)

8
Kush

Punkte, die bei der Erweiterung von SQLiteOpenHelper zu beachten sind

  1. super(context, DBName, null, DBversion); - Dies sollte in der ersten Zeile des Konstruktors aufgerufen werden
  2. Überschreiben Sie onCreate und onUpgrade (falls erforderlich)
  3. onCreate wird nur aufgerufen, wenn getWritableDatabase() oder getReadableDatabase() ausgeführt wird. Dies wird nur einmal aufgerufen, wenn eine im ersten Schritt angegebene DBName nicht verfügbar ist. Sie können eine Tabellenabfrage für die onCreate-Methode hinzufügen
  4. Wenn Sie eine neue Tabelle hinzufügen möchten, ändern Sie einfach DBversion und führen Sie die Abfragen in der Tabelle onUpgrade durch.
4
JibinNajeeb

onCreate wird zum ersten Mal aufgerufen, wenn Tabellen erstellt werden müssen. Wir müssen diese Methode überschreiben, in der wir das Skript zur Tabellenerstellung schreiben, das von SQLiteDatabase ausgeführt wird. execSQL-Methode. Nach der erstmaligen Bereitstellung wird diese Methode nicht mehr aufgerufen.

onUpgrade Diese Methode wird aufgerufen, wenn die Datenbankversion aktualisiert wird. Angenommen, bei der ersten Bereitstellung war die Datenbankversion 1, und bei der zweiten Bereitstellung gab es Änderungen in der Datenbankstruktur, z. Angenommen, die Datenbankversion ist jetzt 2.

Sie können Datenbank & Tabelle erstellen 

public class DbHelper extends SQLiteOpenHelper {
private static final String DBNAME = "testdatbase.db";
private static final int VERSION = 1;

public DbHelper(Context context) {
    super(context, DBNAME, null, VERSION);
    // TODO Auto-generated constructor stub
}

@Override
public void onCreate(SQLiteDatabase db) {
    // TODO Auto-generated method stub
    db.execSQL("create table BookDb(id integer primary key autoincrement,BookName text,Author text,IssuedOn text,DueDate text,Fine text,Totalfine text");

}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL("DROP TABLE IF EXISTS BookDb");
    onCreate(db);
  }
}

Hinweis: Wenn Sie eine andere Tabelle erstellen oder Spalten hinzufügen oder keine solche Tabelle hinzufügen möchten, erhöhen Sie einfach die VERSION

2
Enamul Haque

Wenn Sie vergessen, dem Konstruktor eine Zeichenfolge "name" als zweites Argument anzugeben, wird eine Datenbank "im Arbeitsspeicher" erstellt, die beim Schließen der App gelöscht wird.

1
phreakhead

eine solche Tabelle wird nicht gefunden, wenn Sie die SQLiteOpenHelper-Klasse nicht mit getwritabledata() geöffnet haben und davor müssen Sie auch build-Konstruktor mit databasename & version aufrufen. Und OnUpgrade wird aufgerufen, wenn in der Versionsnummer ein Upgrade-Wert in der SQLiteOpenHelper-Klasse angegeben ist.

Nachfolgend finden Sie den Code-Ausschnitt (Keine der gefundenen Spalten kann aufgrund eines Buchstabens im Spaltennamen sein):

public class database_db {
    entry_data endb;
    String file_name="Record.db";
    SQLiteDatabase sq;
    public database_db(Context c)
    {
        endb=new entry_data(c, file_name, null, 8);
    }
    public database_db open()
    {
        sq=endb.getWritableDatabase();
        return this;
    }
    public Cursor getdata(String table)
    {
        return sq.query(table, null, null, null, null, null, null);
    }
    public long insert_data(String table,ContentValues value)
    {
        return sq.insert(table, null, value);
    }
    public void close()
    {
        sq.close();
    }
    public void delete(String table)
    {
        sq.delete(table,null,null);
    }
}
class entry_data extends SQLiteOpenHelper
{

    public entry_data(Context context, String name, SQLiteDatabase.CursorFactory factory,
                      int version) {
        super(context, name, factory, version);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void onCreate(SQLiteDatabase sqdb) {
        // TODO Auto-generated method stub

        sqdb.execSQL("CREATE TABLE IF NOT EXISTS 'YOUR_TABLE_NAME'(Column_1 text not null,Column_2 text not null);");

    }

    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
          onCreate(db);
    }

}
1
Bharat Lalwani

Überprüfen Sie Ihre Abfrage erneut in der DatabaseHandler/DatabaseManager-Klasse (je nachdem, was Sie angenommen haben).

0
venu

Deinstallieren Sie Ihre Anwendung vom Emulator oder Gerät. Führen Sie die App erneut aus. (OnCreate () wird nicht ausgeführt, wenn die Datenbank bereits vorhanden ist)

0
Nand gopal

Ihr Datenbankname muss mit .db enden. Ihre Abfragezeichenfolgen müssen ein Abschlusszeichen (;) enthalten.

0
Omer Haqqani

Die Sqlite-Datenbank überschreibt zwei Methoden 

1) onCreate (): Diese Methode wurde nur einmal aufgerufen, wenn die Anwendung zum ersten Mal gestartet wird. So rief es nur einmal an 

2) onUpgrade () Diese Methode wurde aufgerufen, wenn wir die Datenbankversion ändern. Dann werden diese Methoden aufgerufen. Sie wird für die Änderung der Tabellenstruktur verwendet

0