Reputation: 91
I m using SQLite database of Android to save text. I earlier had 2 columns and the table was crated like this
db.execSQL("create table Storage(id integer PRIMARY KEY AUTOINCREMENT,title text,body text)");
Afterwards I had a need of adding a new column so i just added a new line in the above code anf then it looked like this
db.execSQL("create table EasyPadStorage(id integer PRIMARY KEY AUTOINCREMENT,title text,body text,color text)"); //Added a column named colors
Now whenever i start the app it throws the crash message saying my app has unfortunately closed. I did some research and found a few soultions but no one helped. I used the following onUpgrade methods
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion == 1 && newVersion == 2) {
db.execSQL("DROP TABLE IF EXISTS" + Tablename);
db.execSQL("DROP TABLE IF EXISTS" + Tablename2);
onCreate(db);
}
}
I do not have any hesitation to use drop the table but if ALTER could work please guide me how to. Either by dropping the table or by using ALTER i just want that my app doesn't crash because of upgrade in tables When i push the update. My database class earlier looked like.
public class SaveN extends SQLiteOpenHelper {
public static final String Databasename = "easypad.db";
public static final String Title = "title";
public static final String Body = "body";
public static final String Tablename = "EasyPadStorage";
public static final String Tablename2 = "details";
Context context;
public SaveN(Context context) {
super(context, Databasename, null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table Storage(id integer PRIMARY KEY AUTOINCREMENT,title text,body text)");
db.execSQL("create table details(name text,image blob)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS" + Tablename);
db.execSQL("DROP TABLE IF EXISTS" + Tablename2);
}
And Now after the changes I've made and methods I've tried to not let my App crash(but failed) looks like this
public SaveN(Context context) {
super(context, Databasename,null,DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table Storage(id integer PRIMARY KEY AUTOINCREMENT,title text,body text,color text)");
db.execSQL("create table details(name text,image blob)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion == 1 && newVersion == 2) {
db.execSQL("DROP TABLE IF EXISTS" + Tablename);
db.execSQL("DROP TABLE IF EXISTS" + Tablename2);
onCreate(db);
}
}
Upvotes: 2
Views: 3681
Reputation: 38605
When you need to update the schema of your database you need to do three things:
onCreate()
. New
installs will go through this method call and have their schema
created here.onUpgrade()
. Existing users who already have a database and update the app will go through this method call.It appears you did step #1 already by adding ,color text
in your creation statement. It's not clear whether you did step #3 because in one version you use a literal 1
and in another you have a named constant DATABASE_VERSION
. As long as this value is greater than 1
, then you have completed step #3.
For step #2, you currently have code to drop your tables and go to onCreate()
to build them again. This isn't necessary for the upgrade you are doing (adding a column), instead you can do
switch (oldVersion) {
case 1:
db.execSQL("ALTER TABLE Storage ADD COLUMN color text");
// no break, in case user is upgrading multiple versions
}
In general this is preferable because dropping tables will result in losing user data (unless temporarily store that data elsewhere and restore it later).
Aside: Your code is prone to bugs because you have named constants for things like table names and column names, but you are inconsistent between using those constants vs typing them out manually in your SQL statements. For example
public static final String Tablename = "EasyPadStorage";
...
db.execSQL("create table Storage(...)");
...
db.execSQL("DROP TABLE IF EXISTS" + Tablename);
Notice the DROP TABLE
statement will actually not do anything because the table was created with the name Storage
--typed manually in SQL--but your constant has the value EasyPadStorage
. Also, you would need a space after the EXISTS
or the SQL will be invalid, which may be the source of the crash you alluded to (but we can't confirm that without a stack trace).
Upvotes: 5