I currently use a sqlite database for an application in both iOS and Android. I don't wish to move onto CoreData or JSON at present for this application as it works perfectly well with the sqlite database.
However I would like to update one of the tables in the database on my next update.
I presumed this would be something that many people would do but interestingly I've tried searching for answers but getting no results.
So my question is two-fold:
1) Is it possible to replace a table within a sqlite database?
2) If so, how does one go about doing this?
I have no code to share as I can't determine how to even start.
Thanks in advance
1) Is it possible to replace a table within a sqlite database?
Yes.
2) If so, how does one go about doing this?
You utilise a means of detecting that a change (an upgrade) is required.
On Android if using a subclass of SQLiteOpenHelper then you increase the version number (4th parameter of the super call), in which case the onUpgrade method runs, so you override the onUpgrade method to handle the update to the table(s).
This utilises the user_version field that is stored in the database's header. In short the SQliteOpenHelper when opening the databases compares the value in the header with the value passed as the 4th parameter. If the passed value is greater than the header value onUpgrade is called. If the values are the same then no such call is made. If the passed value is lower than the value in the header then onDownGrade is called which unless coded results in an exception. (typically onDowngrade is not utilised)
On IOS you could replicate this methodology of comparing a value stored in the user_version extracted via PRAGMA user_version and set via the PRAGMA user_version = ? against a value that indicates a newer version when applicable (i.e. that is not stored in the database). This isn't the only solution
The link above has a brief description which includes a link in relation to SQLite's ALTER TABLE, that itself explains the limitations of the ALTER TABLE command and has a section that covers alternative solutions. This would apply to both IOS and Android.
Related
Android Room version 1.1.0 now provides the method clearAllTables().
Altough this method is very convenient, it does not clear the auto-increment value generated by the by autoGenerate(), as stated in the official documentation.
I would also like to clear the primary keys of all the tables in my database, without having to call individual queries for each table.
Based on this answer, I would assume that this SQL statement would work:
DELETE FROM sqlite_sequence WHERE name='table1' OR name='table2';
...chaining on as many OR clauses as needed.
However, sqlite_sequence is not a Room-managed table, so you may need to execute this SQL using a SupportSQLiteDatabase. You get one of those by calling getOpenHelper().getWritableDatabase() on your RoomDatabase.
However, I would not bother with this. IMHO, you should not be relying on any particular behavior of AUTOINCREMENT (e.g., always starting from some specific value). In that case, it's unclear what value there is in hacking SQLite to reset these values.
I would like to know if it is possible to recover the old database data after upgrading to new database version of Android SQLite?
Thank you.
You cannot get the previous version database data because now it is upgraded.
You can take backup of each version before doing upgrade
Refer this :
Backup/restore sqlite db in android
Not if any of the old data has been changed (unless you can easily determine what has been changed and you can undo the changes).
It is possible to change the version number back using PRAGMA user_version = ?, where ? is an integer representing the version number to be changed to. This literally only changes that value (Offset 60 in the DB header). user_version pragma. If changing the the actual stored version number, then you would have to consider the coded version number as used by the super call, if they differ then onUpgrade or onDownGrade would be called. That is the value as stored in the DB header is compared to the value provided in the code by the super call.
You could alternatively change the version number passed to the Database Helper (subclass of SQLiteOpenHelper) BUT this would result in an exception unless the onDownGrade method was Overridden.
However, this method is not abstract, so it is not mandatory for a
customer to implement it. If not overridden, default implementation
will reject downgrade and throws SQLiteException. onDowngrade
The version number, as stored in the database, has no influence itself over the data. It's really a convenience value and it just so happens that SQLiteOpenHelper makes use of the value.
The database itself is just a file to back it up you just copy the file to restore it you basically copy it back. However, implementing backup and restore will only be of use after it has been implemented.
I am creating a simple application that uses a database derived from db = SQLiteDatabase.openOrCreateDatabase(...). Now, when I create it I use db.setVersion(1);
And I read somewhere that I have to change the database version each time I change it. Now I can't find the particular tutorial where I read this, so I am left with some questions.
1)What is the reason behind versioning of a database? What is a practical purpose?
2)When exactly should the version be updated? After every insert? Every additional table added?
3)Will I be in trouble if I don't update the versions after 1? What would it lead to?
1)Versioning the database is really versioning your schema. This allows you to know when the schema is changed so you can convert it.
2)Whenever you change the schema.
3)If you change the schema, you won't know which one is being used and will end up with exceptions. If you never change the schema, nothing will happen.
And you shouldn't be manually calling setVersion. It already knows the version for an existing one, and you pass in the version elsewhere if its a new database.
The SQLite Database Version In Android is only neccessary if you manage database creation and version updates with the SQLiteOpenHelper.
SQLiteOpenHelper takes care of
opening the database if it exists,
creating it if it does not exis,
upgrading its schema if necessary
sets the SQLite Database Version.
The databaseverionnumber is set in the SQLiteDatabase-constructor.
Your example SQLiteDatabase.openOrCreateDatabase(...) does not use SQLiteOpenHelper so in this case there is no need set the dbversion.
In my android app, I was using a standard SQLite database with a helper class that had 1 table with 3 columns. In the most recent update I had to add another column of to the table, but some users have reported crashes, which (judging by the stack trace) I think comes from the new version trying to read from a column that does not exist because the data is from the old version. How can I protect the users' data between updates short of a manual backup and restore?
Here is the link to the complete updated database class:
https://github.com/cjbrooks12/scripturememory/blob/working/src/com/caseybrooks/scripturememory/databases/VersesDatabase.java
SQLiteOpenHelper will handle the database versioning, you will just have to provide it with proper database version numbers and overridden callbacks. Looking at your code:
Your DB_VERSION is 1. When you change the database schema between released versions, you should increment this number. The version number is stored in the database file, and if the version provided in code is different from the one stored in file, onUpgrade() or onDowngrade() will be called accordingly. In your case, since the database file already exists, no onCreate() was called and since the version numbers matched, no upgrade was performed.
Your onUpgrade() drops the table and then recreates it. In some cases this might be ok, say, it's just a cached copy of data stored elsewhere, but usually as a user, I don't want an app upgrade to delete my data. Implement onUpgrade() so that it does the necessary schema modifications while preserving data. Some generic strategies for this:
If it's just adding some columns ALTER TABLE and put some suitable default values.
If it's more complex schema change, rename the old tables to temporary names, create new tables and then migrate data from the temp tables.
In any case, after onUpgrade() the database schema should be in the same shape it would be if onCreate() was called to create a new database, but with existing data preserved.
I hava an android application which consists sqlite database in the assets folder.
In the DB I have several tables, which one of them is user data (which is updated over time by using the application - when the user installs the application this table is empty).
The other tables store data that I update.
The question is: when a user gets an updated version of my application (with sqlite database in the assets folder) from the market, I need to keep the data the user updated by using the application, but i do want to update the other tables (which consist my data).
What is the correct way to do it?
Thank You :)
Keep a version number for each change and implement the onUpgrade method for the possible combinations. See more in the javadoc for SQLiteOpenHelper
Since you said your tables are empty when the Database is first created, it shouldn't be necessary to add the Database from the /assets-folder.
Instead, you can use a SQLiteOpenHelper, which offers an onCreate()-method that can do the initial table-creation (an add some example data if necessary).
If you then update your app, you simply increase the Database-version and the onUpgrade()-method is called, where you can then perform the Database update.
See this other question: Run some code when user update my app
If your app comes with a huge Database and inserting entry's in the SQLiteOpenHelper isn't the right way to go, you can still check if the Database already exists and then do the updating (through the onUpgrade()-method) and keep the users data.