I m following this tutorial.http://www.androidhive.info/2011/11/android-sqlite-database-tutorial/
can any body please make me clear this chunk of code.
// Creating Tables
#Override
public void onCreate(SQLiteDatabase db) {
String CREATE_CONTACTS_TABLE = "CREATE TABLE " + TABLE_CONTACTS + "("
+ KEY_ID + " INTEGER PRIMARY KEY," + KEY_NAME + " TEXT,"
+ KEY_PH_NO + " TEXT" + ")";
db.execSQL(CREATE_CONTACTS_TABLE);
}
// Upgrading database
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Drop older table if existed
db.execSQL("DROP TABLE IF EXISTS " + TABLE_CONTACTS);
// Create tables again
onCreate(db);
}
Questions
What is the purpose of onUpgrade(); method?
When it is Called? as docs says this is Called when the database needs to be upgraded what does it means by upgrading the database?
Important
why we drop the table in this method and recreate?
Thanks in advance.
onUpgrade is basically for handling new db changes(could be new columns addition,table addition) for any new version of your app.
Droping the table is not always necessary in onUpgrade it all depends on what your use case is. If the requirment is to not to persists the data from your older version of app then drop should help,but if its like changing schema then it should only have alter scripts.
Upgrade means changes have been made to the database schema(version numbers are different) and it needs to be upgraded. Dropping the table and recreating is one way to do that. You could also issue "alter table" statements.
When you open your database it checks the version number and whether or not it exists. You can just "upgrade" your database rather than creating it new.
A good tutorial: http://www.vogella.com/articles/AndroidSQLite/article.html
This method is called when you update your database version. It drops the existing tables and creates it again when onCreate method is called again.
Replying to your 4 questions:
1) The purpose of onUpgrade is to manage a new database structure. You could start you app with simple features, then you need for instance to add a new column, so you need to increase the version of your database from 1 to 2 and in onUpgrade
give the instruction to add a new column, so that if the user update the app, the new column become added.
2) onUpgrade is called when you have a new version of your database and you incremented the int number in the super method( here is 1, so you eventually change it to 2)
public static class DatabaseHelper extends SQLiteOpenHelper{
DatabaseHelper(Context context){
super (context,DATABASE_NAME,null,1);
}
3) Please see above regarding what does it means to update the db
4) We Drop the table and recreate, because to modify the table (example for adding a new column that fits a new feature) a logic way to proceed could be, before to "destroy"/DROP the table and then create a new one with all the data. But this can be not the way to go although recreating the data could mean that the id numbers will be consecutive( usually are not consecutive: you could have 1, 2, and..4 because 3 has been deleted), hence dropping and then creating the table again, and eventually loading the previous data you could have this id consistency.
Sometimes you may want to use ALTER instead of DROP. Why? Usually because using DROP the user loses the content already has in the database, then if you want to learn more about Best practices and more complex real life scenarios please have a look at this amazing reply
Related
Whenever I try to run my project second time (doesnt matter if I change anything or not), I end up getting a crash. If I change the db name or version, the application starts working again.
As far as I have understood (I am new to Android Development), that after you do getWritableDatabase() the database is actually created. After that, if the database is created for the first time, the onCreate method is called in the helper class, otherwise onUpgrade is called (please correct me on the last phrase). Now my OnCreate and OnUpgrade are fairly simple:
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_TABLE_TOI);
db.execSQL(CREATE_TABLE_HINDU);
db.execSQL(CREATE_TABLE_NEWSPAPER);
db.execSQL(CREATE_TABLE_CATEGORY);
db.execSQL(CREATE_TABLE_NEWSPAPER_CATEGORY);
Log.d(TAG, "in onCreate MySQLhelper");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+ newVersion + ", which will destroy all data");
db.execSQL("DROP TABLE IF EXISTS " + TABLE_TOI);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_HINDU);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NEWSPAPER);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_CATEGORY);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NEWSPAPER_CATEGORY);
onCreate(db);
}
After the getWritableDatabase command in my DAO class, I call a class Tables where I use SQLiteStatement to preload the tables. This is where the app crashes. From the logcat, the error being "Caused by: android.database.sqlite.SQLiteConstraintException: PRIMARY KEY must be unique (code 19)".
I dont remember where but I read somewher on StackOverflow regarding a problem (I dont remember the problem either), the answer was to change the database name and try, and it had worked for OP. I tried the same and it worked for me.
So now, I have to change the database name or number for every run.
My Files:
Logcat
Tables.java
MySQLiteHelper.java
Every time you create an instance of Tables, you are inserting data into the database. This does not make much sense in general -- probably you want to move that logic into onCreate() of you MySQLiteHelper class.
If for some reason you really do want to insert data every time you create an instance of Tables, you need to use unique values for your PRIMARY KEY columns. Your current code tries to insert 1, 2, 3, and 4 each time for your four rows. That will work the first time, but the second time, those rows are already there, and so you get the unique-constraint violation.
I am breaking out each SQLite table's code (including initial construction of the table as well as operations on that table) into separate classes extending SQLiteOpenHelper.
In order to get these tables to be created (that is to say, to get the onCreate() method to be called), I have to increment the DATABASE_VERSION (see my own answer here for the details).
But with this methodology, I end up with different version numbers for each class/table - I had to set the DATABASE_VERSION value for the second table I created to 2, I will have to set the third one to 3, etc.
So I will end up with multiple different version values for the same DATABASE (*.db file). If they are all the same val, the onUpgrade() method does not get called, and thus, the onCreate() method is not called, and thus the new table is not created.
Is this "okay" - having a database with several different simultaneous version numbers?
The only other (reasonable) option I know of is to put all the DB code (covering multiple tables) into a single class that extends SQLiteOpenHelper - is doing so actually the preferred method? IOW, is my separation of the db code into several classes, one for each table, a help or a hindrance?
UPDATE
So this is my non-destructive way (by inserting "IF NOT EXISTS" into the DDL) to gradually add new tables, using, per CommonsWare's advice, just one class that extends SQLiteOpenHelper:
#Override
public void onCreate(SQLiteDatabase db) {
String CONDITIONALLY_CREATE_VENDORS_TABLE = "CREATE TABLE IF NOT EXISTS " +
TABLE_VENDORS + "("
+ COLUMN_ID + " INTEGER PRIMARY KEY," + COLUMN_VENDORID
+ " TEXT," + COLUMN_COMPANYNAME + " TEXT" + ")";
db.execSQL(CONDITIONALLY_CREATE_VENDORS_TABLE);
// add more tables as needed following the pattern above
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//db.execSQL("DROP TABLE IF EXISTS " + TABLE_VENDORS); <= Only need to DROP if the table's structure changes; so comment such a line out for the particular table in that case
onCreate(db);
}
NOTE: Whenever I do add a new table, I have to "up" (increment) the DATABASE_VERSION value, so that onUpgrade()/onCreate() are called.
I am breaking out each SQLite table's code (including initial construction of the table as well as operations on that table) into separate classes extending SQLiteOpenHelper
It is important, for thread safety among other reasons, to have a single instance of SQLiteDatabase that you use consistently. That in turn, will require you to have a single SQLiteOpenHelper class. The exception would be for totally independent database files (one SQLiteHelper per database), but that's not usually needed.
Is this "okay" - having a database with several different simultaneous version numbers?
That is not "okay" at all. The highest number wins.
The only other (reasonable) option I know of is to put all the DB code (covering multiple tables) into a single class that extends SQLiteOpenHelper - is doing so actually the preferred method? IOW, is my separation of the db code into several classes, one for each table, a help or a hindrance?
Breaking out "the db code into several classes, one for each table" is not necessarily a problem. What is a problem is having them be independent subclasses of SQLiteOpenHelper.
Let's say that you want these classes not merely to handle table creation and upgrades, but also other CRUD operations related to the table. Having a dedicated class for that is fine. However, the table creation and upgrade logic needs to be driven by a single SQLiteOpenHelper class. Simply have onCreate() and onUpgrade() on your SQLiteOpenHelper delegate the actual work to the per-table classes. This way, you get your code organization, without having multiple SQLiteOpenHelper classes.
I am about to release an Android app and I am a little bit concerned about the database versioning.
The thing is I only use the database during execution time, everytime I start the application I remove all the contents because they donĀ“t need to be persistant. The code is like this:
public synchronized void createDatabase() {
if (database == null) {
database = this.openOrCreateDatabase(DATABASENAME, MODE_PRIVATE, null);
}
database.execSQL("DROP TABLE IF EXISTS " + Xxxxxxxx.TABLE_NAME);
database.execSQL("DROP TABLE IF EXISTS " + Yyyyyyyy.TABLE_NAME);
database.execSQL("DROP TABLE IF EXISTS " + Oooooooo.TABLE_NAME);
database.execSQL("DROP TABLE IF EXISTS " + Ppppppppp.TABLE_NAME);
database.execSQL("DROP TABLE IF EXISTS " + Mmmmmmmmm.TABLE_NAME);
database.execSQL("DROP TABLE IF EXISTS " + Aaaaaaaaa.TABLE_NAME);
database.execSQL(Xxxxxxxx.CREATE_PROVIDERS_TABLE);
database.execSQL(Yyyyyyyy.CREATE_CONTENTS_TABLE);
database.execSQL(Oooooooo.CREATE_EVENTS_TABLE);
database.execSQL(Ppppppppp.CREATE_EVENTS_ANSWERS_TABLE);
database.execSQL(Mmmmmmmmm.CREATE_CATEGORY_TABLE);
database.execSQL(Aaaaaaaaa.CREATE_SUBCATEGORY_TABLE);
}
My question is, considering how I remove everything when I start the app, do I need to control different versions? What if in the future I add a new column? Will it work propperly?
Thanks in advance
I think you don't need to worry at all about db versioning.
If you actually change the DB schema in a future version it doesn't matter since all the tables will be dropped/recreated at next launch.
considering how I remove everything when I start the app, do I need to control different versions? What if in the future I add a new column? Will it work propperly?
you are dropping all the tables and recreating them so you did not need to control the version of your database, you have to change the version of database if you upgrade the existing database and modify the tables. hope this will help
I have an application published in the android market, and now I want to make a new version with changes in the database. The problem is, my version of the app that is already published has this onUpgrade method:
#Override
public void onUpgrade(SQLiteDatabase _db, int _oldVersion, int _newVersion) {
Log.w("TaskDBAdapter", "Upgrading from version " +
_oldVersion + " to " +
_newVersion + ", which will destroy all old data");
// Drop the old table.
_db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE_1);
_db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE_2);
// Create a new one.
onCreate(_db);
}
Because I want to add a new table, I know that I have to make some changes here to keep the data from the tables I already created with the previous version. So what onUpgrade method will be called, from the old or from the new .apk. Can I keep the data from the tables? Please let me know.
Thank u in advance.
So what onUpgrade method will be called, from the old or from the new .apk.
From new .apk. Old one is gone at this point.
Can I keep the data from the tables?
You have to code your upgrade in such a way that you retain data that you need including old data as required.
Dropping the tables will kill all of your current data. In order to preserve the data, you're going to need to write a custom onUpgrade method to do this. Here's a previous post that discusses this and may give you some ideas on what you need to do:
SQLiteOpenHelper onUpgrade() Confusion Android
I'm adding a table to my app's SQLite DB. All my syntax there is fine, not the issue. But I'm having some trouble getting the new table to be created properly. I added the new table....
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DATABASE_CREATE);
db.execSQL(CREATE_REQUESTS);
db.execSQL(CREATE_OVERRIDE);
}
My on create method. I have 3 tables. When I updated the version number, I got an error saying "table requests (referring to CREATE_REQUESTS) has already been created." A look at my onUpgrade method...
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS contacts");
onCreate(db);
}
Led me to understand that the line db.execSQL("DROP TABLE IF EXISTS contacts"), which refers to my DATABASE_CREATE table in the onCreate method, is used to drop the old table, then the next line, onCreate(db); recreates it. I did not add requests into that execSQL line, which is what caused the error. Here is the issue: I would rather not lose the data in the two tables I already have. Is there a way to add a table like I am trying to do, and not lose all the old data? Thanks.
You can do anything you want in onUpgrade. You can use ALTER to add new columns to your table.
Worst case, if your schema is completely and entirely different, you'll have to create the new table, populate it using data from the old table, and then delete the old table.
In any case, onUpgrade was designed to allow for a smooth upgrade without any loss of data. It's just up to you to implement it properly.
if DB version : 6
Ex : There is a table with 5 columns
When you upgrade to : 7 ( I am adding 1 new column in the 3 tables)
1. We need to add the columns when creating a table
2. onUpgrade method:
if (oldVersion < 7)
{
db.execSQL(DATABASE_ALTER_ADD_PAPER_PAID);
db.execSQL(DATABASE_ALTER_LAST_UPLOADED);
db.execSQL(DATABASE_ALTER_PAPER_LABEL);
}
Where : "DATABASE_ALTER_ADD_PAPER_PAID" is query.
EX: public static final String DATABASE_ALTER_ADD_PAPER_PAID = "ALTER TABLE "
+ TableConstants.MY_PAPERS_TABLE + " ADD COLUMN " + COLUMN_PAPER_PAID + " TEXT;";
After above two operation it will works fine for the fresh install user and app upgrade user