Is the onUpgrade
method of SQLiteOpenHelper
ever called? If so, when is it called and by what? If it is not called by the developers, then why is it there? What really happens with that function? I have seen examples where it drops all the tables, but then a comment says that dropping all the tables is not what you should do. Any suggestions?

- 1,778
- 4
- 19
- 36

- 53,877
- 76
- 193
- 251
6 Answers
For those of you who would like to know the exact moment when onUpgrade()
gets called, it is during a call to either getReadableDatabase()
or getWriteableDatabase()
.
To those who are not clear how it ensure it gets triggered, the answer is: It is triggered when the database version provided to the constructor of SqLiteOpenHelper
is updated. Here is a example
public class dbSchemaHelper extends SQLiteOpenHelper {
private String sql;
private final String D_TAG = "FundExpense";
//update this to get onUpgrade() method of sqliteopenhelper class called
static final int DB_VERSION = 2;
static final String DB_NAME = "fundExpenseManager";
public dbSchemaHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
// TODO Auto-generated constructor stub
}
now to...onUpgrade()
@Override
public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
sql = "ALTER TABLE " + fundExpenseSchema.Expense.TABLE_NAME + " ADD COLUMN " + fundExpenseSchema.Expense.FUNDID + " INTEGER";
arg0.execSQL(sql);
}
-
3Actually onUpgrade is called only if you call getWriteableDatabase(). – Yaroslav Mytkalyk Jan 13 '14 at 15:59
-
1@DoctororDrive - also called on `getReadableDatabase()`; both call `getDatabaseLocked(boolean writable)` – CJBS Sep 12 '14 at 21:32
-
Injecting dbVersion from an external config file (as shown in sample by @dev.serghini) would make testing the upgrade code easier by just calling the helper from test code. – Basel Shishani Jul 21 '16 at 08:14
if your are using the SQLiteOpenHelper the onUpgrade will be called whenever you change the DB version. There is an additional requirement for this to work. The db name has to remain the same.
Old Version:
dbName = "mydb.db"
dbVersion = 1
New Version:
dbName = "mydb.db"
dbVersion = 2
in the onCreate of the content provider you create an instance of the SQLiteOpenHelper that takes these params. Your SQLiteOpenHelper implementation would look like this:
public static final class MySQLiteOpenHelper extends SQLiteOpenHelper {
public MySQLiteOpenHelper(Context context, int dbVersion, String dbName) {
super(context, dbName, null, dbVersion);
}
@Override
public void onCreate(SQLiteDatabase db) {
//Code to create your db here
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Code to upgrade your db here
}
}

- 2,989
- 1
- 17
- 8
-
@dev.serghini Where did you find information that changing DB version name only trigger `onUpgrade`? I need official confirmation for this and I cannot find it in the official java docs of this method. – sandalone Aug 19 '13 at 17:27
-
2so then a new question arise: When is the "dbVersion" changed? does the developer control that? like the "appVersion" of the app? – sports Apr 14 '14 at 00:30
It is called when you construct a SQLiteOpenHelper with version newer than the version of the opened database. What to do depends on the changes in the database that are made between the old and new versions. The only case when you don't drop a changed table is when the change is noting more than an added column. Then you can use ALTER TABLE statement to add the new column to the table signature.

- 11,451
- 4
- 35
- 33
-
4The change could also be adding new tables, in which case you might not drop any existing tables. – CommonsWare Jul 02 '10 at 07:49
-
3But how would yo know ahead of time that you will modify a table? Or do you just have to change the method every time you publish an update. – Mohit Deshpande Jul 02 '10 at 13:26
-
3You know when you're changing the database and add another case in onUpgrade. So when the user updates the app, the SQLiteOpenHelper knows that the existing database is obsolete and takes the according action. Check out a piece of Android source for reference: http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java – ognian Jul 02 '10 at 13:42
-
2For quick access to the code that @ognian was referencing in your browser, look at [DatabaseHelper on GrepCode](http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/com/android/providers/settings/DatabaseHelper.java#DatabaseHelper). – hotshot309 Jan 27 '12 at 16:11
-
@ognian So for the very first time, there wont be any onUpgrade method called, right? It will call the constructor and then call onCreate. It's only when I change the version number, it will call onUpgrade instead of onCreate. right? – Kraken Jan 19 '14 at 10:01
Reviewing all of the posts and running debug code it still was not clear to me when I would see onUpgrade getting called. I was starting to think that Android had a serious flaw..
The info on this page led me to my final resolution. Thanks a bunch to all contributors!
This solved it for me...
public class DatabaseHelper extends SQLiteOpenHelper {
public static String TAG = DatabaseHelper.class.getName();
private static final int DATABASE_VERSION = 42;
private static final String DATABASE_NAME = "app_database";
private static final String OLD_TABLE = "old_and_useless";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion ) {
if( newVersion > oldVersion) {
Log.d( TAG, "cool! you noticed." );
db.execSQL( "DROP TABLE IF EXISTS " + OLD_TABLE );
// other calls like onCreate if necessary
} else {
Log.d( TAG, "Hey! didn't you see me?" );
}
}
public void checkDatabaseVersion() {
SQLiteDatabase db = this.getWritableDatabase();
// if the DATABASE_VERSION is newer
// onUpgrade is called before this is reached
}
// other code removed for readability...
}
It's true that getWritableDatabase() and getReadableDatabase() does result in the onUpgrade call. I didn't check other methods since these fit the bill for my needs.
Keep reading, the kicker is coming...
This code in my initial Activity enlightened me when I finally realized that the db version was updating during my debugging... ugh!
DatabaseHelper dbHelper = new DatabaseHelper( this );
dbHelper.checkDatabaseVersion();
NOTE: calling the DatabaseHelper constructor updates the db version
After the constructor call, the db was tagged with the new version. Kill the app before a call to getWritableDatabase() or getReadableDatabase() and you're on the new version. Thereafter new executions never call the onUpgrade method until DATABASE_VERSION is increased again. (sigh! now it seems ridiculously obvious :)
My suggestion is to add some sort of "checkDatabaseVersion()" to the early stages of your app. Alternately, if you create a SQLiteOpenHelper object make sure you call one of the methods (getWritableDatabase(), getReadableDatabase(), etc.) before your app dies..
I hope this saves someone else the same head scratching!... :p

- 141
- 2
- 6
Looking into the SqliteOpenHelper
source code, we can know onCreate()
,onUpgrade()
and onDowngrade
get called in getWritableDatabase()
or getReadableDatabase()
method.
public SQLiteDatabase getWritableDatabase() {
synchronized (this) {
return getDatabaseLocked(true);
}
}
public SQLiteDatabase getReadableDatabase() {
synchronized (this) {
return getDatabaseLocked(false);
}
}
private SQLiteDatabase getDatabaseLocked(boolean writable) {
if (mDatabase != null) {
if (!mDatabase.isOpen()) {
// Darn! The user closed the database by calling mDatabase.close().
mDatabase = null;
} else if (!writable || !mDatabase.isReadOnly()) {
// The database is already open for business.
return mDatabase;
}
}
. . . . . .
final int version = db.getVersion();
if (version != mNewVersion) {
if (db.isReadOnly()) {
throw new SQLiteException("Can't upgrade read-only database from version " +
db.getVersion() + " to " + mNewVersion + ": " + mName);
}
db.beginTransaction();
try {
if (version == 0) {
onCreate(db);
} else {
if (version > mNewVersion) {
onDowngrade(db, version, mNewVersion);
} else {
onUpgrade(db, version, mNewVersion);
}
}
db.setVersion(mNewVersion);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
onOpen(db);
if (db.isReadOnly()) {
Log.w(TAG, "Opened " + mName + " in read-only mode");
}
mDatabase = db;
return db;
} finally {
mIsInitializing = false;
if (db != null && db != mDatabase) {
db.close();
}
}
}

- 1,148
- 1
- 16
- 20
It is actually called when you call getReadableDatabase
or getWritableDatabase
.
Deep dive:
You pass version number in the constructor of SQLiteOpenHelper
which is stored in a variable called mNewVersion
. That's it. Nothing happens at this point.
Everytime you call getReadableDatabase or getWritableDatabase, it will call a method called getDatabaseLocked
. This method will get the existing version number of the database and compare it with the mNewVersion
.
- If the database with the given name doesn't exist it will call
onCreate
- If the new version is greater than old version it will call
onUpgrade
. - If the new version is lower than existing version, an exception will be thrown.
- If they are equal it will go ahead and open the database.
What should I write in onCreate and onUpgrade ?
onCreate
should contain the code that creates a schema for the first time.
You can leave onUpgrade
empty first time since it won't be called the first time. When you want to change the table structure at later stage, that code should go in here.
SQLiteOpenHelper.java(Source code)
public SQLiteDatabase getWritableDatabase() {
synchronized (this) {
return getDatabaseLocked(true);
}
}
public SQLiteDatabase getReadableDatabase() {
synchronized (this) {
return getDatabaseLocked(false);
}
}
private SQLiteDatabase getDatabaseLocked(boolean writable) {
.
.
final int version = db.getVersion();
if (version != mNewVersion) {
if (db.isReadOnly()) {
throw new SQLiteException("Can't upgrade read-only database from version " +
db.getVersion() + " to " + mNewVersion + ": " + mName);
}
db.beginTransaction();
try {
if (version == 0) {
onCreate(db);
} else {
if (version > mNewVersion) {
onDowngrade(db, version, mNewVersion);
} else {
onUpgrade(db, version, mNewVersion);
}
}
db.setVersion(mNewVersion);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
onOpen(db);
}

- 4,626
- 34
- 26