web-dev-qa-db-fra.com

Base de données SQLite Android, table WHY et recréation lors de la mise à niveau

Dans les tutoriels que je suis en train de suivre et dans bien d’autres endroits, je vois ceci: OnUpgrade -> drop table, si existant, puis recréer table.

Quel est le but de ceci?

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

Je conviens que lors de la mise à niveau, vous devez ajouter des colonnes ou des tables à votre base de données. La plupart des échantillons onupgrade sont vraiment nuls parce que je supprime toutes ces données, puis je recrée la table? J'ai trouvé cette entrée de blog que j'appelle la méthode de mise à jour incrémentielle Adams. Il gère également les situations dans lesquelles les utilisateurs n'ont peut-être pas mis à niveau votre application avec chaque version.

Voici un bon blog sur sqlite onupgrade qui ne fait pas tomber la table.

32
danny117

Eh bien, la méthode la plus courante dans les applications Android consiste à "reloger" l'utilisateur lorsqu'une mise à niveau de la base de données est en ordre. Et étant donné que toute base de données locale ne devrait refléter que ce qui se trouve sur l’application côté serveur, il est beaucoup plus facile de simplement la supprimer, la recréer et de la remplir à partir du serveur que de planifier soigneusement les migrations d’une version à l’autre.

Ce n’est certainement pas l’approche best, mais c’est plus facile.

Pour donner un exemple de la mise en œuvre d'une migration (passage d'une version plus ancienne d'une base de données à une nouvelle)

Disons que dans votre classe DbHelper, vous définissez que votre base de données est la version 1; dans une version ultérieure de votre application (version 2), vous avez besoin de quelques colonnes supplémentaires dans l'une de vos tables. 

Il vous faudra donc mettre à jour votre table et ajouter les colonnes via ALTER TABLE {tableName} ADD COLUMN COLNew {type};

Vérifiez ce lien pour cela -> Insérer une nouvelle colonne dans la table dans sqlite?

votre méthode onUpgrade() devra donc refléter ce changement en ajoutant:

 @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

Dépend du type d’approche que vous souhaitez créer et de l’importance de vos données, de la complexité de la table, etc. .. Exemple: si votre application a été mise à niveau à maintes reprises et que la structure de la table a suffisamment changé, elle est meilleure. Pour supprimer la table et la recréer, plutôt que d'écrire du code pour modifier la structure de chaque version de la base de données, vous devrez, dans cette approche, vous assurer que vous pouvez sauvegarder toutes les données dont vous disposez côté serveur, afin que les choses se passent bien.

D'après mon exp: Recréer est mieux si on peut juger qu'il pourrait y avoir d'autres changements dans le futur, sinon ça devient assez compliqué

3
viv

C'est un début propre. La méthode onCreate a la structure de base de données actuellement valide. Les utilisateurs qui installent l'application exécuteront cette méthode. Pour les utilisateurs en cours de mise à niveau, la méthode onUpgrade sera exécutée et DROP TABLE IF EXIST est un nouveau départ - au cas où la structure de l'ancienne et de la nouvelle table serait différente, supprimez-la puis recréez-la dans la méthode onCreate .J'espère que cela t'aides! :)

2
MSquare

si vous souhaitez conserver les données de la table, vous pouvez les transférer dans des fichiers CSV, puis les INSÉRER une fois les tables créées. (inutile de transférer les données sur un serveur) Voici un exemple de code pour le transfert de données. vous pouvez définir le nom du fichier comme étant le nom de la table. le curseur est créé à partir d'une instruction getAll

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

voici un exemple de code pour insérer les données. en supposant que le nom du fichier CSV est identique au nom de la table

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
    }

pour parcourir plusieurs fichiers csv, on peut utiliser le code suivant

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

NOTE: readFromFile (base de données, csvfile); est la fonction précédente

0
hyena