My app uses two databases (separate files). To handle these databases I have created two Helper classes which extend SQLiteOpenHelper, one for each database.
I am no
You need an abstract class that implements the upgrade process described here. Then you extend this abstract class for each of your tables. In your abstract class you must store you tables in a way(list, hardcoded) so when the onUpgrade fires you iterate over the table items and for each table item you do the described steps. They will be self upgraded, keeping all their existing details. Please note that the onUpgrade event fires only once per database, that's why you need to iterate over all your tables to do the upgrade of all of them. You maintain only 1 version number over all the database.
if not exists
(we are doing an upgrade, so the table might not exists yet, it will fail alter and drop)List<String> columns = DBUtils.GetColumns(db, TableName);
ALTER table " + TableName + " RENAME TO 'temp_" + TableName
)columns.retainAll(DBUtils.GetColumns(db, TableName));
)String cols = StringUtils.join(columns, ",");
db.execSQL(String.format(
"INSERT INTO %s (%s) SELECT %s from temp_%s",
TableName, cols, cols, TableName));
)DROP table 'temp_" + TableName
)(This doesn't handle table downgrade, if you rename a column, you don't get the existing data transfered as the column names do not match).
.
public static List<String> GetColumns(SQLiteDatabase db, String tableName) {
List<String> ar = null;
Cursor c = null;
try {
c = db.rawQuery("select * from " + tableName + " limit 1", null);
if (c != null) {
ar = new ArrayList<String>(Arrays.asList(c.getColumnNames()));
}
} catch (Exception e) {
Log.v(tableName, e.getMessage(), e);
e.printStackTrace();
} finally {
if (c != null)
c.close();
}
return ar;
}
public static String join(List<String> list, String delim) {
StringBuilder buf = new StringBuilder();
int num = list.size();
for (int i = 0; i < num; i++) {
if (i != 0)
buf.append(delim);
buf.append((String) list.get(i));
}
return buf.toString();
}
Of course, you can. It is just a matter of your Helper class design. You can just pass the name of DB to your Helper class constructor (along with required Context
instance) instead of hardcoding:
public class DBOpenHelper extends SQLiteOpenHelper {
public DBOpenHelper(Context context, String dbName, int dbVersion) {
super(context, dbName, null, dbVersion);
}
...
}