Update specific table when onUpgrade with SQLite with provided database - android

Probably there is somewhere here answer to my question, but if it exist I can't find it.
Here is my problem:
I have provided database in assets folder. When I want to update my app because I put some more rows in specific table I increase db version, call this.getWritableDatabase(); and onUpgrade is called, to this point everything is ok.
But what next?
Here is my onUpgrade function:
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i2) {
if(i < i2) {
SQLiteDatabase db = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null,SQLiteDatabase.OPEN_READWRITE);
db.execSQL("attach database ? as newdb", new String[]{DB_PATH + DB_NAME}); // I have to attach new version of db to the old one and then i can go on
db.execSQL("delete from GAME");
db.execSQL("INSERT INTO GAME SELECT * FROM newdb.GAME");
db.close();
}
This gives me an error that my db is locked - on the line:
db.execSQL("INSERT INTO GAME SELECT * FROM newdb.GAME");
I tried a lot of different scenarious but I just can't make it.
I'll be very glad if someone could help me make it works ;)

If your onUpgrade does not use its first parameter, it does something wrong.
db and newdb are the same database (both times opened with DB_PATH + DB_NAME).
You probably want to replace db with sqLiteDatabase.

onUpgrade means that you want to upgrade your database, not to copy some data from old one to new. this method gives you all you need to do upgrade - db instance to roll upgrade scripts for specific version. SQL is very powerful you can add/remove columns, delete tables and so on, so I don't see a reason to make another file.

Related

Android SQLite Alter table rename not commit

Thanks in advance.
I need to reestructure my database in the new version of my app, and then I use onUpgrade method in my SQLiteOpenHelper class for this purpose.
Well, I need to rename some columns, and how it is not possible in sqlite I decided to create another table, import all data and then delete the old table and rename de new table. All in "onUpgrade" method... well, at the end of the method I need to upload the database to a server, when I walk thought tables I found that cursor returns nullpointer because it not found the new fields, but in fact when I go to de file explorer in DDMS and view the database from my phone I see that fields are inside.
It seems that changes not commit, but I use databasetransaction for this purpose.
What I do wrong?
My code in onupgrade seems like that:
public void onUpgrade(final SQLiteDatabase db, int oldVersion, int newVersion) {
if(oldVersion==22 && newVersion==23){
try {
db.beginTransaction();
db.execSQL("CREATE TABLE unidades2 (uuid text, nombre TEXT)");
c=db.rawQuery("SELECT * FROM unidades",null);
c.moveToFirst();
while(!c.isAfterLast()){
auxuuid=new uuid().toString();
db.execSQL("INSERT INTO unidades2(uuid, nombre) VALUES (?,?)",new String[] {auxuuid,c.getString(1)});
c.moveToNext();
}
c.close();
db.execSQL("DROP TABLE unidades");
db.execSQL("ALTER TABLE unidades2 RENAME TO unidades");
db.setTransactionSuccessful();
}
finally db.endTransaction();
}
}
And then walking through unidades table whith a cursor, and do:
try {
db.beginTransaction();
Cursor cursor = db.rawQuery("SELECT * FROM unidades",null);
cursor.moveToFirst();
int hasuuid= cursor.getColumnIndex("uuid");
cursor.close();
[Code uploading database in JSON]
db.setTransactionSuccessful();
}
finally db.endTransaction();
hasuuid its -1.
Please help me!! Thanks a lot.
One issue that might cause the problem though it's not apparent in the snippets you posted: onUpgrade() is already run inside a transaction. sqlite itself does not support nested transactions. The Android wrapper on top adds partial support so that nested transactions are only committed or rolled back once the outermost transaction is committed or rolled back. The outermost transaction in this case being the one set up before onUpgrade() was called. So when you think you commit, no actual commit is performed on sqlite database level.

The best way to overwrite an SQLite database table in Android?

When there is new data available to my Android application I need to completely remove all current entries in one of the SQLite database tables and replace them all with the new data. What is the best way to do this?
Would it be best to run
DELETE * FROM my_table
or
run a delete query for every row in the database
or run
database.execSQL(DATABASE_DROP_MY_TABLE);
database.execSQL(DATABASE_CREATE_MY_TABLE);
Where DATABASE_DROP_MY_TABLE is SQL to drop the table and DATABASE_CREATE_MY_TABLE is
SQL to create the table again with no entries.
And then following one of these, insert the new data.
Of course there are probably other ways to do this that I have not thought of.
Assuming you're using SQLiteOpenHelper, you can just close db, delete the whole file and recreate the db:
class MyDatabase extends SQLiteOpenHelper {
public static final String DB_NAME = "wat";
public MyDatabase(Context context) {
super(context, DB_NAME, null, CURRENT_VERSION);
}
}
dbHelper.close(); // dbHelper is your MyDatabase instance
context.deleteDatabase(DB_NAME);
SQLiteDatabase db = dbHelper.getWritableDatabase() // will create empty db
Nice thing about this solution is that you won't have to update table resetting code when you add new tables to your schema. It also correctly recreates indexes you might have added.
I wouldn't complicate things, and simply drop the table with DROP TABLE statement. As the doc say:
The SQLite DROP TABLE statement is used to remove a table definition and all associated data, indexes, triggers, constraints and permission specifications for that table.
You would have clean plate, then create the table again and add your new data.

Upgrading Sqlite database in android?

I have an android application which is using Sqlite as database.It has following tables:
Hotels
Locations
Favorites
I am keeping my raw database file in assests folder and when user installs my app i just copies this database to /data/data/package_name/databases directory.Initially Favorites table is empty and it gets populated after user start liking hotels.My problem is that I want to launch my updated version of app with some bug fixes and some new hotels added to the database, so I need to update database of existing users with new hotels and locations without affecting the favorites table.Now if I keep my old approach and update the Database Version Number then application will remove the old database and use the new database but all data in favorites table will be lost.I don't want it to happen.Now problem is how do I update Hotels and Locations table without loosing data in Favorites table.
I know this question was asked long ago, but I had a similar issue and wanted to share my solution, seems to do the trick for me. I'm a novice so feel free to give input-
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//code to keep table data
List<obj> objList = new ArrayList<obj>();
String selectQuery = "SELECT score,list_name,quiz_length FROM obj_table";
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
obj o = new obj();
o.final_score = cursor.getInt(0);
o.quiz_name = cursor.getString(1);
o.quiz_length = cursor.getInt(2);
objList.add(o);
} while (cursor.moveToNext());
}
//done storing data, now upgrade DB from asset file
try {
//my db file is upgraded here
copyDataBase();
} catch (IOException e) {
}
//now insert our saved table data
for (Score obj_rec: objList){
ContentValues values = new ContentValues();
values.put("score", obj_rec.final_score);
values.put("list_name", obj_rec.quiz_name);
values.put("quiz_length", obj_rec.quiz_length);
db.insert("obj_table", null, values);
}
}
Before updating write the contents of you previous table to a file and save it on the sdcard.
Then you may update your database with new version.
And after doing that copy back the data from the backup file(from sdcard) to the updated database. After the successful copying of the backup, delete the file from the sdcard.
Usualy upgrade a database has to be done with SQLiteOpenHelper class. I would advise You to do some tests at Your own device before publish it. You have to increment Your Database Version and call "ALTER TABLE" method from sqlite. This has been discussed in many threads here, the clearest one I think is this one:
Difficulty in upgrading SQlite table
and here is even a article with some solution:
http://joshhendo.blogspot.de/2012/03/android-sqlite-database-upgrade.html
However, a safe way would be to save the old database in a tempfolder, that the user can get back the old one if anything is running into chaos.

Android does not update SQLite database

I am experiencing some trouble with an SQLIte database in my Android application.
The issue is that the database is never updated, not even on multiple restarts of the emulator, of Eclipse or after deletion from DDMS.
This is my onCreate method, located in a class that extends SQLiteOpenHelper:
public void onCreate(SQLiteDatabase database) {
try {
database.execSQL(ESSENCE_TABLE_CREATE);
database.execSQL(PACCO_TABLE_CREATE);
database.execSQL(TAVOLE_TABLE_CREATE);
database.rawQuery("insert into essenza values(1, 'Rovere')",
null); // added later
} catch (SQLException e) {
Log.e("DB", e.getMessage());
}
}
After instantiating the helper, I request a reference to the database:
helper = new DBHelper(context, dbpath + "/" + DATABASE_NAME);
database = helper.getWritableDatabase();
It seems that the rawQuery statement (which was added at a later time) is not executed and that the database in use is instead cached from a previous version. I also tried to change the version of the database, but it did not work. Am I missing something? Thanks in advance.
You have two options:
Use DDMs to delete the database file from your device (look in /data/data/). This will force Android to run onCreate again.
In your constructor, increment the database version you pass to SQLiteOpenHelper. Add your raw query to onUpgrade.
You probably want option 1. Option 2 is better if you have users of your app whose databases you want to update.

Android update SQLite DB schema?

What is the best practice for updating the DB schema? I could send a text file with the SQL commands. The app could check the text file and execute the commands needed. I am guessing then I will have a flag to indicate that the update has been done. I havent found a way to delete a file in the asset folder from the app, which would be the best thing to do after the DB was updated.
Any thoughts on this?
You will probably want to override
onUpdate(SQLiteDatabase db,int old Version,int newVerison)
The following tutorial can walk you through the process: http://www.codeproject.com/KB/android/AndroidSQLite.aspx
What is the best practice for updating the DB schema?
Use SQLiteOpenHelper. The only time you will be updating your schema is when you update the application. Whether you have the SQL commands in a file that you read in or just in your Java code is up to you.
I am guessing then I will have a flag to indicate that the update has been done.
That is part of what SQLiteOpenHelper gives you.
I havent found a way to delete a file in the asset folder from the app, which would be the best thing to do after the DB was updated.
That is not possible, sorry.
As mentioned from others the SQLiteOpenHelper is the thing you are starting with.
Depending on your environment and requirements, Liquibase may be worth a look. It allows writing your update statements in a more structural way and is easier to use than plain SQL operations. I haven't used it for android, though.
If you want to update the db schema use the following code in your SQLiteOpenHelper extended class. This will update the table structure and never lose your saved data from db,
public void onUpgrade(SQLiteDatabase db, int oldVersion, int
newVersion) {
if (oldVersion < newVersion)
{
db.execSQL("ALTER TABLE " + "TABLE_NAME" + " TO " +
"NEW_TABLE_NAME");
db.execSQL("ALTER TABLE " + "TABLE_NAME" + " ADD COLUMN " +
"FIELD_NAME" + " INTEGER;");
}
}
SQLite doesn't support removing or modifying columns.

Categories

Resources