There is a parameter in the constructor of the virtual class SQLiteOpenHelper called version(like below shows)
public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) {
this(context, name, factory, version, null);
}
What i want to know is what's the meaning of the version?Can anyone help me on this?
Its the Database version you ship with the Application. So in the future if you want to add a table or delete a column or anything which differs from the previous Database version. This version Number will come handy.
This is an example of how I manuplated DB on upgrades of my application:
The method is defined by the framework, onUpgrade()
Class Level Variable:
private static final int DATABASE_VERSION = 4;
Check against the current version:
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < 2) {
db.execSQL(DATABASE_CREATEX);
}
if (oldVersion < 3) {
db.execSQL(DATABASE_CREATEC);
}
if (oldVersion < 4) {
final String ALTER_TBL = "ALTER TABLE " + DATABASE_TABLE1
+ " ADD COLUMN Vcost text;";
final String ALTER_TBL1 = "ALTER TABLE " + DATABASE_TABLE1
+ " ADD COLUMN Vmedicine text;";
db.execSQL(ALTER_TBL);
db.execSQL(ALTER_TBL1);
final String ALTER_TBL2 = "ALTER TABLE " + DATABASE_TABLE2
+ " ADD COLUMN Dcost text;";
final String ALTER_TBL3 = "ALTER TABLE " + DATABASE_TABLE2
+ " ADD COLUMN Dmedicine text;";
db.execSQL(ALTER_TBL2);
db.execSQL(ALTER_TBL3);
}
}
So it checks based on all versions of the DB and it acts according to the current version which is present on the device.
Its a way for you to version your database, which is why you're also required to override the onUpgrade method to handle database upgrades. So say you launch your app with a SQLite database and then later on you change your tables. You would then increment the database version, and when the app updates the onUpgrade method would be executed.
Version :
number of the database (starting at 1); if the database is older, onUpgrade(SQLiteDatabase, int, int) will be used to upgrade the database; if the database is newer, onDowngrade(SQLiteDatabase, int, int) will be used to downgrade the database
for more detail visit this
Related
I already have a database in my app using a 3rd party library. The library doesn't seem to have drop table functionality. So I was thinking to directly change it using SQLiteOpenHelper API. Is this possible?
I have created a class that extends SQLiteOpenHelper and give it the same db name as the one used in the library.
public class SqliteDatabaseHelper extends SQLiteOpenHelper {
// Database Info
private static final String DATABASE_NAME = "myDatabase";
private static final int DATABASE_VERSION = 1;
private Context context;
public SqliteDatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.context = context;
}
#Override
public void onCreate(SQLiteDatabase db) {
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
L.w("old: " + oldVersion + ", " + "new: " + newVersion);
if (oldVersion != newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + "deals_latest");
onCreate(db);
L.w("drop it like it's hot");
}
}
}
And I initialize it in Application class, just to see if it reflects the db class I created.
SQLiteDatabase db = new SqliteDatabaseHelper(this).getReadableDatabase();
L.w("version: " + db.getVersion());
L.w("path: " + db.getPath());
SqliteDatabaseHelper helper = new SqliteDatabaseHelper(this);
helper.onUpgrade(db, 1, 2); // this line suppose to invoke the drop table query
When running the app, onUpgrade() method doesn't seem to be called.
Mind you, I have never had any experience in using the native SQLite helper, so I have no idea what is going on here. My objective is just to see if the query in onUpgrade is executed or not. But the table still exists in the database.
How do I get around this?
The SQLiteOpenHelper class helps to manage versions of your own database.
It does not make sense to use it for a database that is managed by third-party code.
Just open the database directly with openDatabase().
I learned a way which use SQLite3 on Android OS recently.
But it has a non acceptable part.
I can't understand why drop the table when called "onUpgrade" method of SQLiteOpenHelper.
Why need "onUpgarde" method?
If code executes "drop table", table data of old version DB will be removed, isn't it?
Why delete existing data of old DB?
How to restore existing DB data when drop the table?
[Here is learned code]
public class MySQLiteOpenHelper extends SQLiteOpenHelper {
final String CONFIRMED_SHEETS_TABLE = "confirmed_sheets";
public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
#Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
String sql = "create table" +
CONFIRMED_SHEETS_TABLE +
"_id integer primary key autoincrement, " +
"group text, " +
"num001 text, " +
"num002 text, " +
"num003 text, " +
"num004 text, " +
"num005 text, " +
"num006 text, " +
"date text)";
sqLiteDatabase.execSQL(sql);
}
#Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
// non acceptable part //
String sql = "drop table if exists " + CONFIRMED_SHEETS_TABLE;
sqLiteDatabase.execSQL(sql);
onCreate(sqLiteDatabase);
}
}
If code executes "drop table", DB table data of old version DB will be
removed, isn't it?
Yup
Why need "onUpgrade" method?
If you are switching databases (for example because you added a new column), your app (usually) now depends on that change. Increasing the database version in your Helper class calls onUpgrade(), which allows you to take care of any migration to prepare the app to use your new schema.
Did you know why learned code executes "drop table"?
Convenience. It's not necessarily the right approach, but a database change can make it hard to take old data and merge it in the new table. Thus, it is easier logic-wise to simply start anew.
If you want to merge an existing and new table, have a look at this question.
You do not need to perform a DROP TABLE in onUpgrade(), as it is currently written in your code. The purpose of onUpgrade() is for your app to check if a new version of your app's database is being installed on a user's device, and if so, if there are any changes to your database, such as adding a new column, you can make those changes within onUpgrade(). If you never change your database schema, you never need to do anything in onUpgrade().
For more information and a introductory tutorial on Databases in Android, refer to the Notepad sample code here.
EDIT: also, here's an example of an onUpgrade() I wrote for one of my apps:
/**
* Handle upgrades to the database.
*/
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if(DBG) Utils.log(TAG, "DBHelper: onUpgrade()...");
// Logs that the database is being upgraded
Utils.log(TAG, "w", "Upgrading database from version " + oldVersion + " to "
+ newVersion);
/*
* Every time you add new columns to the database in the phone, you will want
* to increment the Database version above and then add a condition in here for
* upgrading to it. Otherwise it will cause upgrading users to be nontrivial and
* lead to unnecessary crashes or upgrade instructions.
*/
if (newVersion > oldVersion && newVersion <= 4) {
db.execSQL("ALTER TABLE " + TrackerDb.SomeTable.TABLE_NAME + " ADD COLUMN "
+ TrackerDb.SomeTable.COLUMN_NAME_DATE_MODIFIED + " TEXT");
}
}
OnUpgrade() is called when db versions "old and new" does not match; which means that the user wants to change Database Structure (Dropping a table, Adding new Table, Modifying Table definition).
So the OnUpgrade() should contain the logic as:
Take Backup of the existing data (e.g. Generate insert statements for existing
data).
Modify Database Structure accordingly.
Restore the data from the backup.
I have uploaded an application to play store couple of weeks back. This application involves sqlite database that stores information on username, password, other details that given are by user while using the application locally.
Now I have couple of more tables and fields added to database and wanna upload the application to playstore as an update?
My worry is if the user updates the application from playstore - After update - all the data stored in database will be saved or will the user has to recreate everything from scratch?
Let me know!
Thanks!
You have to override the onUpgade method of SQLiteOpenHelper. In the OnUpgrade method you can either erase the data(drop sqlite command) or maintain the data with the additional columns(alter sqlite command) or create new table (create sqlite command).
Refer the following snippet.
I assume your version would be 1.(Plz check the constructor of your SqliteOpenHelper class)
Increment the version by 1.
class DatabaseHelper extends SqliteOplenHelper{
private static final int DATABASE_VERSION = 2; //new version of the database
private static final int Database_name = "MyDatabase";
private static final String alterUserName = "alter table users add name text";
private static final String table_users = "create table if not exists "
+ users + "(" + "_id integer primary key autoincrement,"
+ "email text" + ")";
public DatabaseHelper(Context context) {
super(context, Database_name, null, DATABASE_VERSION);
cntxt = context;
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(table_users);
db.execSQL(alterUserName);
}
}
Now everytime when you roll the next update with database changes be sure to increment the database version by 1 else let it remain the same.
This isn't done for you automatically. In your SQLiteOpenHelper, you need to increment the Schema integer. This will trigger the on upgrade method for your existing users.
Adding a table is not a problem, just do this in onUpgrade, nothing breaks.
However to add fields, you should use the 'ALTER TABLE' SQL command
If you add new columns you can use ALTER TABLE to insert them into a live table. If you rename or remove columns you can use ALTER TABLE to rename the old table, then create the new table and then populate the new table with the contents of the old tab
See the official reference here
I'm getting this error -
07-03 12:29:18.643: E/SQLiteLog(5181): (1) table accounts has no column named otherNotes
This is my code:
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "accountsManager";
private static final String TABLE_ACCOUNTS = "accounts";
private static final String KEY_ID = "id";
private static final String KEY_TITLE = "title";
private static final String KEY_USERID = "userId";
private static final String KEY_PASSWORD = "password";
private static final String KEY_LOGINURL = "loginUrl";
private static final String KEY_OTHERNOTES = "otherNotes";
public DatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public void onCreate(SQLiteDatabase db) {
String CREATE_ACCOUNTS_TABLE = "CREATE TABLE " + TABLE_ACCOUNTS + "("
+ KEY_ID + " INTEGER PRIMARY KEY," + KEY_TITLE + " TEXT,"
+ KEY_USERID + " TEXT," + KEY_PASSWORD + " TEXT," + KEY_LOGINURL + " TEXT,"
+ KEY_OTHERNOTES + " TEXT" + ");";
db.execSQL(CREATE_ACCOUNTS_TABLE);
}
public void addAccount(AccountDetails account) {
SQLiteDatabase db = this.getWritableDatabase();
System.out.println("Hello!");
ContentValues values = new ContentValues();
values.put(KEY_TITLE, account.getTitle()); // Account Title
values.put(KEY_USERID, account.getUserId()); // account userid
values.put(KEY_PASSWORD, account.getPassword()); // account password
values.put(KEY_LOGINURL, account.getLoginUrl()); // account loginurl
values.put(KEY_OTHERNOTES, account.getOtherNotes()); // account othernotes
Log.v("title", KEY_TITLE);
// Inserting Row
db.insert(TABLE_ACCOUNTS, null, values);
db.close(); // Closing database connection
}
Also, when I remove the following statement:
values.put(KEY_OTHERNOTES, account.getOtherNotes()); // account othernotes
Then I get the same problem with password...etc.
i.e, (1) table accounts has no column named password
Please help!!
It seems that you added some columns later in the database. I do agree with Ken Wolf and you should consider uninstalling and re-installing your app. One better approach is, drop and recreate all tables in onUpdate method, and increase the db version every time you change the schema.
Well, If you are confindent about syntax for creating table, than it may happen
when you add new column in your same table, for that...
1) Unistall from your device and run it again.
OR
2) Setting -> app -> ClearData
OR
3) Change DATABASE_NAME in your "DatabaseHandler" class
( I faced same problem. But I suuceed by changing DATABASE_NAME.)
OR
4) Change DATABASE_VERSION in your "DatabaseHandler" class
(If you have added new column than it will upgrade autimatically)
public DatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
As Benil says in a comment above, change the database version number and run the code again.
The SQL code looks fine.
I think that you forgot to call open() on your database object that you created.
add this methods to you SQL class:
private DbHelper ourHelper;
private final Context ourContext;
private SQLiteDatabase ourDatabase;
public DataBaseMain open() throws SQLException{
// Open the database to make her writeable, must be called before writing
// to database
ourHelper = new DbHelper(ourContext);
ourDatabase = ourHelper.getWritableDatabase();
return this;
}
public void close(){
// Closing the database for writing, avoids error.
ourHelper.close();
}
And use when you want to call you DB.
Try "Clear Data " of your App from Settings.
For me this problem was occuring because i was storage data on SD Card and later i added some columns.
So if you are saving on SD card delete the previous data.
For those who have similar problem and above solution is not worked then check 2 things:
Space between column name and data type like
COLUMN_NUMBER+" TEXT PRIMARY KEY) not COLUMN_NUMBER+"TEXT PRIMARY KEY)
The order of column during the creation of table should same as map for data insertion like
ContentValues values = new ContentValues();
values.put(TEST_ID, testId);
values.put(CLASS_NAME, className);
values.put(SUBJECT, subject);
"CREATE TABLE IF NOT EXISTS " + TABLE_NAME + "("
+ COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ TEST_ID + " INTEGER,"
+ CLASS_NAME + " TEXT,"
+ SUBJECT + " TEXT,"
Here It is your query..TRY this.
String CREATE_ACCOUNTS_TABLE = "CREATE TABLE "+TABLE_ACCOUNTS+"(KEY_ID INTEGER PRIMARY KEY,KEY_TITLE TEXT,KEY_USERID TEXT,KEY_PASSWORD TEXT,KEY_LOGINURL TEXT,KEY_OTHERNOTES TEXT);";
It's possible if you made a mistake in creation query and then fix it,
So in the file system you have a db, but this db possibly has no such column.
Solution:
in emulator find a db file: data/data/com.somecompany.yourapp/databases/db and remove it, then try again.
It's also possible to open this file in some sql explorer and check if there is that column.
I ran into the same issue, as I updated my database table in sqlite with new columns during testing phase.
Besides the answers that were already given above, what I found really useful to update SQLite databases (e.g. after changes) is ABD Idea, an AndroidStudio plugin that allows you to:
Uninstall App
List item
Kill App
Start App
Restart App
Clear App Data
Clear App Data and Restart
You can just specify the version like this:
private static final int VERSION = 4;
If your sure your codes are OKAY, just try uninstalling the application, then rerun it agian. This solved my issue. Hope it helped
the possible solution also (not the best one) to use different version of DB, like:
public static final int DATABASE_VERSION = 2;
public DBHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
it works for me.
clearing app data from the phone settings worked in my case.
either in the android emulator, you can do the same.
Current code is
override fun onCreate(db: SQLiteDatabase?) {
val createPWDTable =
"CREATE TABLE IF NOT EXISTS $tblPassword ($pwdId INTEGER PRIMARY KEY autoincrement,$title TEXT,$email TEXT,$pwd TEXT,$notes TEXT);"
db!!.execSQL(createPWDTable)
}
Now add colmn encrypted
override fun onCreate(db: SQLiteDatabase?) {
val createPWDTable =
"CREATE TABLE IF NOT EXISTS $tblPassword ($pwdId INTEGER PRIMARY KEY autoincrement,$title TEXT,$email TEXT,$pwd TEXT,$encrypted INT,$notes TEXT);"
db!!.execSQL(createPWDTable)
}
override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
if (newVersion == 2) {
val query = "ALTER TABLE $tblPassword ADD COLUMN $encrypted INT DEFAULT '0'"
db!!.execSQL(query)
}
}
Here if New user then oncreate method directly create table with encrypted value.
if Old user then onUpgrade method has check db version and alter the table
I know i have replie to this question to late but maybe someone can solve her problem with this answer.
You are put some data later in table database so the best solution is to re name your data base name.
In my case there was a query syntax error (need space b/w column name and datatype ..see attached image) in onCreate() method
to resolve it ..
I followed these steps
Correct your syntax error
change DB version number
Clear App data from settings
Uninstall and Run Your app again.]1]1
Hope it helps
Uninstall your app and reinstall your app and after that it will work fi
I have one problem with Android SQLite database.
I have one table which contains one field.StudentFname
and that application is working fine with Android 2.3.1 and now if I add another field then my application is not working properly.
Can anyone help me who knows database very well,
you can use ALTER TABLE function on your onUpgrade() method, like this:
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// If you need to add a column
if (newVersion > oldVersion) {
db.execSQL("ALTER TABLE foo ADD COLUMN new_column INTEGER DEFAULT 0");
}
}
Obviously, the SQLite will differ depending on the column definition.
I came across this thread when needing help on my own app, but saw issues with many of the answers. I would recommend doing the following:
private static final String DATABASE_ALTER_TEAM_1 = "ALTER TABLE "
+ TABLE_TEAM + " ADD COLUMN " + COLUMN_COACH + " string;";
private static final String DATABASE_ALTER_TEAM_2 = "ALTER TABLE "
+ TABLE_TEAM + " ADD COLUMN " + COLUMN_STADIUM + " string;";
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < 2) {
db.execSQL(DATABASE_ALTER_TEAM_1);
}
if (oldVersion < 3) {
db.execSQL(DATABASE_ALTER_TEAM_2);
}
}
You want to make sure the code will work when users upgrade more than 1 version and that the update statement only runs the one upgrade it is needed. For a bit more on this, check out this blog.
The easiest way to do this is to add some SQL to the onUpgrade() method in your SQLiteOpenHelper class. Something like:
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// If you need to add a new column
if (newVersion > oldVersion) {
db.execSQL("ALTER TABLE student ADD COLUMN student_rollno INTEGER DEFAULT 0");
}
}
Perhaps a slightly more elegant approach using switch instead of if/then that will upgrade from any schema to the most recent schema...
Here's also a decent page on the syntax for altering a table: http://alvinalexander.com/android/sqlite-alter-table-syntax-examples
public static final String TABLE_TEAM = "team";
public static final String COLUMN_COACH = "coach";
public static final String COLUMN_STADIUM = "stadium";
private static final String DATABASE_ALTER_TEAM_TO_V2 = "ALTER TABLE "
+ TABLE_TEAM + " ADD COLUMN " + COLUMN_COACH + " TEXT;";
private static final String DATABASE_ALTER_TEAM_TO_V3 = "ALTER TABLE "
+ TABLE_TEAM + " ADD COLUMN " + COLUMN_STADIUM + " TEXT;";
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion)
{
case 1:
//upgrade from version 1 to 2
db.execSQL(DATABASE_ALTER_TEAM_TO_V2);
case 2:
//upgrade from version 2 to 3
db.execSQL(DATABASE_ALTER_TEAM_TO_V3);
//and so on.. do not add breaks so that switch will
//start at oldVersion, and run straight through to the latest
}
}
I have done the following approach, it is resovled for me
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
#Aamirkhan.i think you would have solved the problem you mentioned in the comments long back ago.i think you didn't increase the data base version. or else the answers here are straight forward.i am writing this because it might help anyone who hasn't increased or changed their data base version number when they are altering a table.
I think we should not check condition like that
if (newVersion > oldVersion) {
}
because if we use this , it means every time when we increase the database version then onUpdrade() will call and condition will be true , so we should check like that
if(oldVersion==1)
{
}
so in this case if old version is 2 then condition will be false and user with old version 2 will not update the database(which user wants only for version 1), because for those users database had already updated .
To add a new column to the table you need to use ALTER. In android you can add the new column inside the onUpgrade().
You may be wonder, how onUpgrade() will add the new column?
When you implementing a subclass of SQLiteOpenHelper, you need to call superclass constructor: super(context, DB_NAME, null, 1); in your class constructor. There I have passed 1 for version.
When I changed the version 1 to above(2 or greater), onUpgrade() will invoked. And perform the SQL modifications which I intend to do.
My class constructor after changed the version:
public DatabaseHelper(Context context) {
super(context, DB_NAME, null, 2);//version changed from 1 to 2
}
SQL modifications checks like this, superclass constructor compares the version of the stored SQLite db file with the version that I passed to super(). If these(previous and now) version numbers are different onUpgrade() gets invoked.
Code should look like this:
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// add new columns to migrate to version 2
if (oldVersion < 2) {
db.execSQL("ALTER TABLE " + TABLE_NAME + "ADD COLUMN school VARCHAR(250)");
}
// add new columns to migrate to version 3
if (oldVersion < 3) {
db.execSQL("ALTER TABLE " + TABLE_NAME + "ADD COLUMN age INTEGER");
}
}
Simply change in your code
private final int DATABASE_VERSION = 1;
to
private static final int DATABASE_VERSION =2;
first, increment the database version number. and then in onUpgrade method, you can check if the column exists already if not then only add the column
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if(!existsColumnInTable(db, TABLE_NAME, COLUMN_NAME)){
db.execSQL("ALTER TABLE foo ADD COLUMN COLUMN_NAME INTEGER DEFAULT 0");
}
}
private boolean existsColumnInTable(SQLiteDatabase inDatabase, String inTable, String columnToCheck) {
Cursor cursor = null;
try {
// Query 1 row
cursor = inDatabase.rawQuery("SELECT * FROM " + inTable + " LIMIT 0", null);
// getColumnIndex() gives us the index (0 to ...) of the column - otherwise we get a -1
if (cursor.getColumnIndex(columnToCheck) != -1)
return true;
else
return false;
} catch (Exception Exp) {
return false;
} finally {
if (cursor != null) cursor.close();
}
}
this method is extracted from this link Checking if a column exists in an application database in Android
I came across link while searching for the same issue. It explains how to use upgrade.
https://thebhwgroup.com/blog/how-android-sqlite-onupgrade
it explains why to use this below code
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < 2) {
db.execSQL(DATABASE_ALTER_TEAM_1);
}
if (oldVersion < 3) {
db.execSQL(DATABASE_ALTER_TEAM_2);
}
}
The easiest way to create a new column on a table is add some SQL to the onUpgrade() method in SQLiteOpenHelper class. Like:
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
case 1:
db.execSQL(SQL_MY_TABLE);
case 2:
db.execSQL("ALTER TABLE myTable ADD COLUMN myNewColumn TEXT");
}
}
Noticed no answers look for the existence of a column:
Cursor cursor = database.rawQuery("SELECT * FROM " + MY_TABLE, null);
int columnIndex = cursor.getColumnIndex(MY_NEW_COLUMN);
if (columnIndex < 0) {
database.execSQL("ALTER TABLE " + MY_TABLE + " ADD COLUMN " + MY_NEW_COLUMN + " TEXT");
}