Base de datos SQLite de Android, WHY drop table y recreate on upgrade

En los tutoriales que estoy siguiendo y en muchos otros lugares, veo esto, onUpgrade -> drop table si existe, luego recrea la tabla.

¿Cuál es el propósito de esto?

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

Acepto que cuando actualice debe agregar columnas o agregar tablas a su base de datos. La mayoría de las muestras de actualización realmente apestan porque ¿por qué elimino todos estos datos y luego vuelvo a crear la tabla? Encontré esta entrada de blog. Lo llamo Método de actualización incremental de Adams . También maneja situaciones en las que los usuarios pueden no haber actualizado su aplicación con cada lanzamiento.

Aquí hay un buen blog sobre sqlite onupgrade que no hace drop table.

Bueno, el método más común en las aplicaciones de Android es “relog” al usuario cuando una actualización de la base de datos está en orden. Y considerando que cualquier base de datos local solo debe reflejar lo que está en la aplicación del lado del servidor, es mucho más fácil simplemente descartar la base de datos, volver a crearla y repoblar desde el servidor que planear cuidadosamente las migraciones de una versión a otra.

Ciertamente no es el mejor enfoque, pero es más fácil.

Para hacer un ejemplo de cómo sería implementar una migración (un cambio de una versión anterior de una base de datos a una más nueva)

Digamos en su clase DbHelper que define que su base de datos es la versión 1, en una versión posterior de su aplicación (versión 2), necesita unas pocas columnas más en una de sus tablas.

Por lo tanto, necesitaría actualizar su tabla y agregar las columnas mediante ALTER TABLE {tableName} ADD COLUMN COLNew {type};

Verifique este enlace para eso -> Inserte una nueva columna en la tabla en sqlite?

entonces su método onUpgrade() tendría que reflejar ese cambio agregando:

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

Depende del tipo de enfoque que desee crear y de la importancia de sus datos, qué complejidad de la tabla es. Ejemplo: si su aplicación se ha actualizado muchas veces y la estructura de la tabla ha cambiado lo suficiente, entonces es mejor dejar la tabla y volver a crearla, en lugar de escribir código para cambiar la estructura de cada versión de db, en este enfoque Tendrá que asegurarse de que puede hacer una copia de seguridad de todos los datos que tenga en el lado del servidor, para que todo siga siendo correcto.

Desde mi experiencia: recrear es mejor si puedes juzgar que podría haber más cambios en el futuro, de lo contrario se vuelve bastante complicado

Es un comienzo limpio. El método onCreate tiene la estructura de la base de datos actualmente válida. Los usuarios que instalen la aplicación ejecutarán este método. Para los usuarios que se están actualizando, se ejecutará el método onUpgrade, y DROP TABLE IF EXIST es un comienzo limpio; en caso de que la estructura de la tabla nueva y la anterior sean diferentes, suéltelo y vuelva a crearlo en el método onCreate. ¡Espero que esto ayude! 🙂

si desea mantener los datos de la tabla, puede volcarlos en archivos CSV y luego INSERTARlos una vez que se hayan creado las tablas. (no hay necesidad de volcar los datos en un servidor) aquí hay un código de muestra para los datos de dumping. puede establecer que el nombre del archivo sea el nombre de la tabla. el cursor se crea a partir de una instrucción 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; } } 

Aquí hay un código de muestra para insertar los datos. asumiendo que el nombre del archivo CSV es el mismo que el nombre de la tabla

 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 } 

para recorrer muchos archivos csv uno puede usar el siguiente código

 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 files = new ArrayList(); 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; } } 

NOTA: readFromFile (base de datos, csvfile); es la función anterior