[android]How to add new column to DB on missing one? - android

I wrote an application in android that using DB.
In the next version I want to add new column to the DB but without re-installing the application. How can I upgrade the table on missing column exception?

You can simply do it by changing(increment) database version
public class Databas extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 2;
Database(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if(oldVersion <= DATABASE_VERSION)
db.execSQL("//write table altering query here ");
onCreate(db);
}
increment database version value with 1 from your current database version value

This can be easily done by using SQLiteOpenHelper. Let say your current database version is 1. You just change it to 2. Then if there is any version 1 database will be automatically update to version 2 and onUpgrade method will be invoked.
private static final String DATABASE_NAME = "data";
private static final String DATABASE_TABLE = "notes";
private static final int DATABASE_VERSION = 2;
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DATABASE_CREATE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if(oldVersion <= 1)
db.execSQL("Do you table alter here ");
onCreate(db);
}
}

Related

Android : Change SQLite DB on upgrade

I want to add a column to my existing database
However I'm imagining I'm in the scenario where people have already got a version of the code and database and I'm going to make the changes through a update on google play, therefore previous data cannot be lost
To create my database I used the following code;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_calculation);
db = openOrCreateDatabase("EJuiceData", Context.MODE_PRIVATE, null);
db.execSQL("create table if not exists Inventory(_id integer primary key autoincrement, NAME TEXT NOT NULL, AMOUNT TEXT, PRICE TEXT, AMOUNTLEFT TEXT, WEIGHT TEXT);");
....
I've looked around online and people are mentioning using the following command to update;
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (newVersion > oldVersion) {
db.execSQL("ALTER TABLE Recipe ADD COLUMN NOTES TEXT");
}
}
However onUpgrade is commented out stating the it isn't being called, also no where in my code have I stated what version of the database it is or given a new version
Anyone know how I get around this issue?
Thanks
EDIT;
From looking at the answers I've decided to try do this the most efficient way and what's seen as the best practice
So I've created a new Java Class called MyDBHelper which has the following
package com.sjhdevelopment.shaunharrison.myejuiceapp;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class MyDBHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "EJuiceData.db";
public static final int DATABASE_VERSION = 1;
public MovieDatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public void onCreate(SQLiteDatabase database) {
database.execSQL("create table if not exists Recipe");
.....
}
#Override
public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) {
if (newVersion > oldVersion)
database.execSQL("ALTER TABLE Recipe ADD COLUMN NOTES TEXT");
onCreate(database);
}
}
So far I have an error on MovieDatabaseHelper stating 'invalid method declared; return type required
Are you using SQLiteOpenHelper ? If yes you must have a version you send to the super class from the constructor (see documentation)
Here is a code sample. The onUpgrade function will be called when the DATABASE_VERSION changes.
public class DatabaseHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "EJuiceData.db";
public DatabaseHelper (Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase database) {
database.execSQL("create table if not exists Inventory(_id integer primary key autoincrement, NAME TEXT NOT NULL, AMOUNT TEXT, PRICE TEXT, AMOUNTLEFT TEXT, WEIGHT TEXT);");
}
#Override
public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) {
if (newVersion > oldVersion) {
db.execSQL("ALTER TABLE Recipe ADD COLUMN NOTES TEXT");
onCreate(database);
}
}
}
EDIT
now you can get access your database using
DatabaseHelper helper = new DatabaseHelper(getContext());
helper.getReadableDatabase().query(...);
//or
helper.getWritableDatabase().insert(...);
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < newVersion)
db.execSQL("DROP TABLE IF EXISTS '" + TABLE_NAME + "'");
onCreate(db);
}
}
You can extend SQLiteOpenHelper like below code, and new your helper class with version param which db version you want to open.
If you open db with version 1, and next time you open db with version 2, the onUpgrade method will be called with param ordVersion = 1 and newVersion = 2, then you can do something to upgrade your db schema here.
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
public class MyDBHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "mydata.db";
public static final int VERSION = 1;
private static SQLiteDatabase database;
public MyDBHelper(Context context, String name, CursorFactory factory,
int version) {
super(context, name, factory, version);
}
public static SQLiteDatabase getDatabase(Context context) {
if (database == null || !database.isOpen()) {
database = new MyDBHelper(context, DATABASE_NAME,
null, VERSION).getWritableDatabase();
}
return database;
}
#Override
public void onCreate(SQLiteDatabase db) {
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
onCreate(db);
}
}

Android SQLite DB Upgrade - Code Structure (works in onUpgrade but not when called from there)

I'm working on upgrading sqlite databases in android. I think I got the principles, but I can't understand the behavior of - in my understanding - similar code versions.
When I directly excecute the "Alter Table"-Command inside the overridden onUpgrade-procedure (Code 1 below), everything is fine. If I call a procedure using exactly the same (sql and java) code inside it (Code 2), the database is not affected. However, there is no error notice, and if I run the sql-code in a sqlite manager after pulling the DB-File using adb it works fine as well.
It would be nice if anyone could explain what is the problem with the "seperated version"?
Note: For creating the database, there is no problem in calling a routine from onCreate...
"Integrated" Version, Code 1, Working:
public class DBHandler extends SQLiteOpenHelper {
private static final String DBName = "DynamicValueTracker.db";
private static final int DBVersion = 2;
public DBHandler(Context context) {
super(context, DBName, null, DBVersion);
mContext = context;
}
#Override
public void onUpgrade(SQLiteDatabase db, int OldVersion, int NewVersion) {
switch (NewVersion) {
//(deleted further cases for posting question...)
//This works
case 2:
String sqlcmd = "ALTER TABLE countries ADD COLUMN capital TEXT DEFAULT null;";
db.execSQL(sqlcmd);
break;
}
}
}
"Seperated" Version, Code 2, Not Working:
public class DBHandler extends SQLiteOpenHelper {
private static final String DBName = "DynamicValueTracker.db";
private static final int DBVersion = 2;
public DBHandler(Context context) {
super(context, DBName, null, DBVersion);
mContext = context;
}
#Override
public void onUpgrade(SQLiteDatabase db, int OldVersion, int NewVersion) {
switch (NewVersion) {
//(deleted further cases for posting question...)
case 2:
DBUpgrade_V1_to_V2(db);
break;
}
}
}
public void DBUpgrade_V1_to_V2(SQLiteDatabase db) {
//This is excecuted without throwing errors but does not change the database table
String sqlcmd = "ALTER TABLE countries ADD COLUMN capital TEXT DEFAULT null;";
db.execSQL(sqlcmd);
}
}

Good schema to delete database file in SQLiteOpenHelper.onDowngrade()

I have an existing database based on SQLiteOpenHelper that has several versions and code to upgrade it and that works fine. But in case a user installs an older version of the app (that expects a lower database version) it will currently crash - the ContentProvider using it can't access the database. I'd like to prevent it from crashing but I don't want to actually downgrade the database - adding the code to do that would be pain. Dropping all tables would certainly work but starting with a fresh file is imo cleaner and less error prone.
That's about what the database helper looks like - nothing special
public class MyDbHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 3;
private static final String DATABASE_NAME = "my.db";
public MyDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
onUpgrade(db, 0, DATABASE_VERSION);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (newVersion < 1) db.execSQL("CREATE TABLE A...");
if (newVersion < 2) db.execSQL("CREATE TABLE B...");
if (newVersion < 3) db.execSQL("CREATE TABLE C...");
}
#Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// I'd like to delete the database here
// the only problem is that I can't from here
// since this is called in the middle of getWritableDatabase()
// and SQLiteDatabase has no .recreate() method.
}
}
The possible ways I've come up to do that are:
Do it from the outside: catch exceptions in the ContentProvider, delete the file and request to open the database again. - I don't like that since it's not the responsibility of the provider.
Replacing SQLiteOpenHelper with my own copy of that class that deletes the file instead of calling onDowngrade - Problem is that it's using package private parts of SQLiteDatabase (e.g. .lock()) which I can't replace without duplicating SQLiteDatabase too (that would probably result in duplicating the whole sqlite stack).
Is there any good approach to do that or do I have to go the DROP TABLES way e.g. like described here?
I've figured out a way that works nicely by extending SQLiteOpenHelper and all I need to do in MyDbHelper is to extend this class.
public abstract class DeletingSQLiteOpenHelper extends SQLiteOpenHelper {
private static final String TAG = DeletingSQLiteOpenHelper.class.getSimpleName();
private final File mDatabaseFile;
public DeletingSQLiteOpenHelper(Context context, String name, CursorFactory factory, int version,
DatabaseErrorHandler errorHandler) {
super(context, name, factory, version, errorHandler);
mDatabaseFile = context.getDatabasePath(name);
}
public DeletingSQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) {
super(context, name, factory, version);
mDatabaseFile = context.getDatabasePath(name);
}
#Override
public synchronized SQLiteDatabase getWritableDatabase() {
try {
return super.getWritableDatabase();
} catch (SQLiteDowngradeFailedException e) {
// that's our notification
}
// try to delete the file
mDatabaseFile.delete()
// now return a freshly created database
return super.getWritableDatabase();
}
#Override
public final void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// throwing a custom Exception to catch it in getWritableDatabase
throw new SQLiteDowngradeFailedException();
}
// that's the exception
static class SQLiteDowngradeFailedException extends SQLiteException {
public SQLiteDowngradeFailedException() {}
public SQLiteDowngradeFailedException(String error) {
super(error);
}
}
}

Android database upgrade Issue

I have a application which has Database
now i want to release new version of the applicaton
but my database has new field added
and i want to keep my old data in database and also add new database with additional fields
Will my database will be overided(i will losse my copy of data) or new database will be added
focus on onUpgrade method :-)
public class WIMProvider extends ContentProvider {
private static final int DATABASE_VERSION = 2;
private DatabaseHelper mOpenHelper;
// ..... code .....
private static class DatabaseHelper extends SQLiteOpenHelper {
private Context mContext;
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
mContext = context;
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion == 1) {
db.execSQL("ALTER TABLE TCategory ADD COLUMN fiDefault integer DEFAULT 0");
oldVersion++;
}
if (oldVersion == 2) {
db.execSQL("ALTER TABLE TCategory ADD COLUMN fsIcon nvarchar(50)");
oldVersion++;
}
}
}

Android: getting rid of your sqlite database

I would to erase and recreate the database for my app each time I send a new version of my app from Eclipse to my phone (I am developing and changing my database very often). What is the easiest way to do this?
public class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context) {
super(context, dbName, null, 1);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE USERS (username TEXT, password TEXT);");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS USERS");
onCreate(db);
}
i use this one in my code :) change super(context, dbName, null, <database version number>); and it will execute onUpgrade method.
If this is something you do not wish to do once it is live, you can just clear data from your application manager each time. Also, you can make the database version number different and have the onUpgrade destroy and recreate the DB
private static final String DATABASE_NAME = "MyDbName";
private static final int DATABASE_VERSION = 6;
private static class DbOpenHelper extends SQLiteOpenHelper{
public DbOpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
onUpgrade(this.getWritableDatabase(), 0, 0);
//
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(TableHelper1.CREATE_TABLE_QUERY);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS "+ TableHelper1.TABLE_NAME);
onCreate(db);
}
}
In Eclipse, go into Debug Configurations, then Android Application on the left hand side. Select the debug configuration that you are using and then select the Target tab.
At the bottom, you'll see a checkbox labeled "Wipe User Data".
If you check that, everytime you launch the simulator, the data associated with your application (including the SQLite database) will be erased.
Your application will then call onCreate() for your SQLiteOpenHelper, and your database will be recreated.

Categories

Resources