web-dev-qa-db-de.com

Android SQLite Database, WARUM Tabelle löschen und beim Upgrade neu erstellen

In den Tutorials, denen ich folge, und an vielen weiteren Stellen sehe ich Folgendes: OnUpgrade -> drop table, falls vorhanden, dann Tabelle neu erstellen.

Was ist der Zweck davon?

private static class DbHelper extends SQLiteOpenHelper{

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

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE " + DATABASE_TABLE + " (" +
                KEY_ROWID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                KEY_NAME + " TEXT NOT NULL, " +
                KEY_HOTNESS + " TEXT NOT NULL);"
        );  
    }

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

Ich stimme zu, wenn Sie ein Upgrade durchführen, sollten Sie Ihrer Datenbank Spalten hinzufügen oder Tabellen hinzufügen. Die meisten Onupgrade-Samples sind wirklich scheiße, weil ich dann alle diese Daten lösche und dann die Tabelle neu aufbaut. Ich fand diesen Blogeintrag, den ich als Adams Incremental Update Method bezeichnet habe. Es behandelt auch Situationen, in denen Benutzer Ihre App möglicherweise nicht mit jeder Version aktualisiert haben.

Hier ist ein guter Blog über sqlite onupgrade, der keine Tabelle ablegen kann.

32
danny117

Nun, die häufigste Methode in Android-Anwendungen besteht darin, den Benutzer "neu zu loggen", wenn ein Datenbank-Upgrade in Ordnung ist. Wenn man bedenkt, dass eine lokale Datenbank nur das widerspiegelt, was sich auf der serverseitigen Anwendung befindet, ist es viel einfacher, die Datenbank einfach zu löschen, neu zu erstellen und vom Server neu zu füllen, als Migrationen von einer Version zur anderen sorgfältig zu planen.

Es ist sicherlich nicht der beste -Ansatz, aber es ist einfacher.

Um ein Beispiel für die Implementierung einer Migration zu geben (eine Änderung von einer älteren auf eine neuere Datenbankversion)

Angenommen, Sie definieren in Ihrer DbHelper-Klasse, dass Ihre Datenbank Version 1 ist. In einer späteren Version Ihrer Anwendung (Version 2) benötigen Sie einige weitere Spalten in einer Ihrer Tabellen. 

Sie müssen also Ihre Tabelle aktualisieren und die Spalten über ALTER TABLE {tableName} ADD COLUMN COLNew {type} hinzufügen.

Überprüfen Sie diesen Link für das -> Fügen Sie in sqlite eine neue Spalte in die Tabelle ein.

ihre onUpgrade()-Methode müsste also diese Änderung widerspiegeln, indem Sie Folgendes hinzufügen:

 @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    switch(oldVersion){
        case 1:
            db.execSQL("ALTER TABLE " + DATABASE_TABLE + " ADD COLUMN " + NEW_COLUMN_NAME + TYPE);
    }
}  
32
Aedis

Hängt von der Art der Vorgehensweise ab, die Sie erstellen möchten, und wie wichtig Ihre Daten sind, wie komplex die Tabelle ist .. _ Beispiel: Wenn Ihre App häufig aktualisiert wurde und sich die Tabellenstruktur häufig geändert hat, ist es besser Um die Tabelle zu löschen und neu zu erstellen, anstatt Code für das Ändern der Struktur für jede Version von db zu schreiben, müssen Sie bei diesem Ansatz sicherstellen, dass Sie alle auf dem Server vorhandenen Daten sichern können, damit die Dinge in Ordnung bleiben.

Aus meiner Sicht: Wiederherstellen ist besser, wenn Sie beurteilen können, dass es in Zukunft weitere Änderungen gibt, sonst wird es ziemlich kompliziert

3
viv

Es ist ein sauberer Anfang. Die Methode onCreate hat die aktuell gültige Datenbankstruktur. Benutzer, die die App installieren, führen diese Methode aus. Für die Benutzer, die ein Upgrade durchführen, wird die Methode onUpgrade ausgeführt, und DROP TABLE IF EXIST ist ein Neustart - nur für den Fall, dass sich die Struktur der alten und der neuen Tabelle unterscheidet. Legen Sie sie ab und erstellen Sie sie in der onCreate-Methode neu. .Hoffe das hilft! :)

2
MSquare

wenn Sie die Tabellendaten pflegen möchten, können Sie sie in CSV-Dateien ablegen und nach dem Erstellen der Tabellen wieder einfügen. (keine Notwendigkeit, die Daten auf einem Server zu sichern) Hier ist ein Beispielcode für das Ablegen von Daten. Sie können den Dateinamen als Tabellennamen festlegen. Der Cursor wird aus einer getAll-Anweisung erstellt

public boolean createCsvSaveToFile(Cursor cursor, String fileName) throws IOException {
    String csv = "";
    int colunmCount = cursor.getColumnCount();
    /* check if extarnal drive is readerble */
    if (!isExternalStorageWritable()) {
        fileError = "can not save to external storage";
        fileinfo = "Please mount your SD card";
        return false;
    } else {
        /* create the CSV */
        for (int i = 0; i < colunmCount; i++) {
            csv += QUOTES + cursor.getColumnName(i).toString() + QUOTES + INNER_DELIMITER;
        }
        csv = csv.replaceAll(",$", "");
        csv += LINE_END;
        if (cursor.moveToFirst()) {
            do {
                for (int i = 0; i < colunmCount; i++) {//GET COLUNM values
                    csv += QUOTES + cursor.getString(i) + QUOTES + INNER_DELIMITER;
                }
                csv = csv.replaceAll(",$", "");
                csv += LINE_END;
            } while (cursor.moveToNext());
        }
        /* save file */
        File file = getDataDir(fileName);
        FileOutputStream out = new FileOutputStream(file);
        out.write(csv.getBytes());
        out.flush();
        out.close();
        return true;
    }
}

hier ist ein Beispielcode zum Einfügen der Daten. Der CSV-Dateiname stimmt mit dem Tabellennamen überein

private void readFromFile(SQLiteDatabase database, File file) {
    boolean hasColunms = false;
    String tableName = file.getName().replaceAll(".csv$", "");
    String sql;
    String colunmNames = "";
    String colunmValues;
    try {
        BufferedReader br = new BufferedReader(new FileReader(file));
        String line;
        while ((line = br.readLine()) != null) {
            if (!hasColunms ) {
                /* get column names */
                line = line.replaceAll("\"", "");
                colunmNames = line;
                hasColunms = true;
            } else {
                line = line.replaceAll("\"", "'");
                colunmValues = line;
                sql = "INSERT INTO " + tableName + " (" + colunmNames + ") VALUES (" + colunmValues + ")";
                database.execSQL(sql);
            }
        }
        br.close();
    } catch (IOException e) {
        database.close();
        /* You may need to add proper error handling here
    }

um viele CSV-Dateien zu durchlaufen, kann der folgende Code verwendet werden

public boolean csvTodatabase(SQLiteDatabase database) {
    FileStuff f = new FileStuff();
    File time;
    /* check if extarnal drive is readerble */
    if (!f.isExternalStorageReadable()) {
        f.fileError = "can not read external storage";
        f.fileinfo = "Please remount your SD card";
        return false;
    } else {
        /* get all files from extarnal drive data */
        ArrayList<File> files = new ArrayList<File>();
        File directory = new File(FileStuff.DATA_DIRECTORY);
        if (!directory.exists()) {
            return false;
        }
        File[] fList = directory.listFiles();
        for (File file : fList) {
            if (file.isFile()) {
                files.add(file);
            }
        }  
        for (File csvfile : files) {
            readFromFile(database, csvfile);
        }
        return true;
    }
}

HINWEIS: readFromFile (Datenbank, CSV-Datei); ist die vorherige Funktion

0
hyena