When does SQLiteOpenHelper onCreate() / onUpgrade() run?
Solution 1:
SQLiteOpenHelper
onCreate()
and onUpgrade()
callbacks are invoked when the database is actually opened, for example by a call to getWritableDatabase()
. The database is not opened when the database helper object itself is created.
SQLiteOpenHelper
versions the database files. The version number is the int
argument passed to the constructor. In the database file, the version number is stored in PRAGMA user_version
.
onCreate()
is only run when the database file did not exist and was just created. If onCreate()
returns successfully (doesn't throw an exception), the database is assumed to be created with the requested version number. As an implication, you should not catch SQLException
s in onCreate()
yourself.
onUpgrade()
is only called when the database file exists but the stored version number is lower than requested in the constructor. The onUpgrade()
should update the table schema to the requested version.
When changing the table schema in code (onCreate()
), you should make sure the database is updated. Two main approaches:
-
Delete the old database file so that
onCreate()
is run again. This is often preferred at development time where you have control over the installed versions and data loss is not an issue. Some ways to delete the database file:Uninstall the application. Use the application manager or
adb uninstall your.package.name
from the shell.Clear application data. Use the application manager.
-
Increment the database version so that
onUpgrade()
is invoked. This is slightly more complicated as more code is needed.For development time schema upgrades where data loss is not an issue, you can just use
execSQL("DROP TABLE IF EXISTS <tablename>")
in to remove your existing tables and callonCreate()
to recreate the database.For released versions, you should implement data migration in
onUpgrade()
so your users don't lose their data.
Solution 2:
To further add missing points here, as per the request by Jaskey
Database version is stored within the SQLite
database file.
catch is the constructor
SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)
So when the database helper constructor is called with a name
(2nd param), platform checks if the database exists or not and if the database exists, it gets the version information from the database file header and triggers the right call back
As already explained in the older answer, if the database with the name doesn't exists, it triggers onCreate
.
Below explanation explains onUpgrade
case with an example.
Say, your first version of application had the DatabaseHelper
(extending SQLiteOpenHelper
) with constructor passing version as 1
and then you provided an upgraded application with the new source code having version passed as 2
, then automatically when the DatabaseHelper
is constructed, platform triggers onUpgrade
by seeing the file already exists, but the version is lower than the current version which you have passed.
Now say you are planing to give a third version of application with db version as 3
(db version is increased only when database schema is to be modified). In such incremental upgrades, you have to write the upgrade logic from each version incrementally for a better maintainable code
Example pseudo code below:
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch(oldVersion) {
case 1:
//upgrade logic from version 1 to 2
case 2:
//upgrade logic from version 2 to 3
case 3:
//upgrade logic from version 3 to 4
break;
default:
throw new IllegalStateException(
"onUpgrade() with unknown oldVersion " + oldVersion);
}
}
Notice the missing break
statement in case 1
and 2
. This is what I mean by incremental upgrade.
Say if the old version is 2
and new version is 4
, then the logic will upgrade the database from 2
to 3
and then to 4
If old version is 3
and new version is 4
, it will just run the upgrade logic for 3
to 4
Solution 3:
onCreate()
When we create DataBase at a first time (i.e Database is not exists)
onCreate()
create database with version which is passed inSQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)
onCreate()
method is creating the tables you’ve defined and executing any other code you’ve written. However, this method will only be called if the SQLite file is missing in your app’s data directory (/data/data/your.apps.classpath/databases
).This method will not be called if you’ve changed your code and relaunched in the emulator. If you want
onCreate()
to run you need to use adb to delete the SQLite database file.
onUpgrade()
-
SQLiteOpenHelper
should call the super constructor. - The
onUpgrade()
method will only be called when the version integer is larger than the current version running in the app. - If you want the
onUpgrade()
method to be called, you need to increment the version number in your code.
Solution 4:
May be I am too late but I would like to share my short and sweet answer. Please check Answer for a same problem. It will definitely help you. No more deep specifications.
If you are confident about syntax for creating table, than it may happen when you add new column in your same table, for that...
1) Uninstall from your device and run it again.
OR
2) Setting -> app -> ClearData
OR
3) Change DATABASE_VERSION
in your "DatabaseHandler" class (If you have added new column than it will upgrade automatically)
public DatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
OR
4) Change DATABASE_NAME
in your "DatabaseHandler" class (I faced same problem. But I succeed by changing DATABASE_NAME
.)