SQLiteDatabase insert or replace if changed - android

I'm looking for a way to fill/update my SQLiteDatabase table.
On some occasions I need to be notified (by certain return value). Each row contains a url of a file that needs to be downloaded later.
row does not exist yet: insert it and notify me that this row should be listed for download.
row does exist but the one I'm trying to insert contains the same values as the one already in the db: do nothing, do not notify me that this should be downloaded.
row does exist and the one I'm trying to insert contains different values as the one already in the db: replace this row, notify me that this should be downloaded.
I've been looking for the answer but can't seem to find something good. Should I use insertWithOnConflict(), replace(), replaceOrThrow(), ...
Thanks!

Do it in two steps wrapped in a single sqlite transaction:
Query by rowid. If no rowid or or no result found, insert new and download.
Compare url of new row and row retrieved in step 1. Only if the urls are different, update the row and download, otherwise no-op.

First, you query if value exist in DB with cursor & if it's null you make an insert otherwise you make an update if the required field is different from what you have already.
In any other case do nothing
// Some pseudocode
Cursor cursor=_db.query("TABLE", null, TABLEID + "=?", new String[]{id}, null, null, null);
if(cursor.getCount()<1) // row Not Exist
{
cursor.close();
....assign values
SQLiteDatabase _db.insert("TABLE_Name", null, Table_object);
download ...ok
}
cursor.moveToFirst();
if( cursor[field] != "same_value" ) {
SQLiteDatabase _db.update("TABLE_Name", null, Table_object);
download ...ok
}

Related

How to get 5 last record in the sqlite db in android?

Since the db does not have create date and some ordering field (but in my observation the last row is the latest record),
so how can i get the five last record in some condition e.g.
five record that their schoolid == 1?
Thanks
public Cursor select()
{
String orderBy = FIELD_pubKey+" DESC";
Cursor cursor = iReadDatabase.query(TABLE_NAME, null, null, null, null, null, orderBy);
cursor.moveToFirst();
return cursor;
}
There's no such thing as a last record or a first or a 42nd.
Which records appears last in the result of a query is dependent on the query plan, or an Explicit order by if you add one.
Select * From Table Where ...
The rows will be returned in whatever order the engine considers suitable at the time.
If you need them in specific order, then add an order by clause to the query, anything else is asking for it.
Something like
Select * From Table Order by SomeColumn desc limit 5
will do what you require.
Now what column you need to order by I've no idea, but you need one that will do the job, assuming automatic primary key, but note it is possible to mess with that.

Imported sqlite database is missing data and mixing columns

I have put an sqlite database in my assets folder and imported it onto the phone.
I created an object with multiple properties and when I create a list of that object and assign each property a value from a column of the table they get mixed up
Below is my code
public ArrayList<Exercise> getExercisesFromQuery(String Query) {
ArrayList<Exercise> ExerciseList = new ArrayList<Exercise>();
Cursor cursor = mDb.rawQuery(Query, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
Exercise e = new Exercise();
e.setID(Integer.parseInt(cursor.getString(0)));
e.setName(cursor.getString(1));
e.setMuscle(cursor.getString(2));
e.setDescription(cursor.getString(3));
e.setFilepath(cursor.getString(4));
e.setSets(cursor.getString(5));
e.setReps(cursor.getString(6));
e.setEquipment(cursor.getString(7));
e.setPrimaryMuscle(cursor.getString(8));
e.setSecondaryMuscle(cursor.getString(9));
e.setDifficulty(cursor.getString(10));
// Adding contact to list
ExerciseList.add(e);
} while (cursor.moveToNext());
}
return ExerciseList;
}
The current problem is when I do object.getName it gives me the muscle and if I do object.getmuscle it is blank and there is no value but if I do object.getDescription it works fine.
It is not a problem with the database it works fine in any sqlite manager.
Any ideas as to what is wrong?
The reason why the columns are not being returned in the order you expect is not clear. They should come back in the order specified in your query or in the order they are on the table if you are doing SELECT *. However it is not really necessary to address that specific puzzle.
A more defensive and maintainable coding approach is to request each column's index from the cursor by using the getColumnIndexOrThrow method instead of hardcoding them. For example:
int ID_INDEX = cursor.getColumnIndexOrThrow("_id");
int NAME_INDEX = cursor.getColumnIndexOrThrow("name");
If the column doesn't exist you'll get an exception. If it does, you now have its index within the cursor which you can use in the calls to cursor.getString:
e.setID(Integer.parseInt(cursor.getString(ID_INDEX)));
e.setName(cursor.getString(NAME_INDEX));
So you no longer need to worry about what order the columns come back in and you won't need to change any hardcoded index values if your query changes in the future.
Make sure that the columns in the database are in the correct order - column Name should be the second column, column Muscle should be the third column.

How to break cursor processing while cursor object hold first row and move to fetch second row?

As I'm fetching only one column from SqLite database but getting more than 1MB of data in my cursor object and I can't split my database query. Is it possible to break cursor processing as soon as cursor fetches first row and at that particular time I want to hold this cursor object values in another object. After that cursor clear this value and move to next for fetching second row in database, this continues till the end of records ?
What if you do the following? (This is just an idea)
Fetch all rows you need with the id column only (fetch the id instead of the blob column).
Iterate throw that cursor and for each line fetch only one row for the given id with your blob. Then you close that Cursor and you open a new one for the next id row:
//just fetch the ids of the wanted rows
Cursor idCursor = db.query("TABLE_NAME",new String[]{"_id"}, null, null, null,null,null);
Cursor blobCursor;
//for each row (id)
while(idCursor.moveToNext())
{
//fetch one row with the blob of the given id
blobCursor = db.query("TABLE_NAME",new String[]{"image"}, "_id = ?", new String[] {new Long(idCursor.getLong(0)).toString()}, null,null,null);
if(blobCursor.moveToFirst())
{
//get the blob and store it
blobCursor.getBlob(0);
}
blobCursor.close(); //close the cursor (and release resources)
}
idCursor.close();
If you are using Cursor(SQLiteCursor) - there is no way to prevent cursor from "eating memory"(break processing as you says) after you fetched first row.
android.database.sqlite is a java wrapper for sqlite3 library which is written on C.
The fact is that sqlite3 has no function to count how much records statement will produce, so you have to scan whole resultset with help of sqlite3_step function until it returns SQLITE3_DONE. SQLiteCursor is derived from CursorWindow.
CursorWindow (has some native methods) at the moment Cursors getCount() method is called first time - it does two things : calculates count of row and caches these rows.
There is custom port(russian) of sqlite3 for android with functionality you need.
If you can not read russian:
java code
native code
native sources

Android delete row with cursor

I am creating a program in Android, on one of the screens I plan to iterate thought the rows in a database, presenting each row to the user and letting him skip it or delete it.
In Java I could user the ResultSet's deleteRow() method, however android currently has no equivalent method. Or event a method to set a column with a mark for deletion.
Would doing the deletion via the SQLiteDatabase delete or executeSql method would the currently opened cursor remain valid and would the deleted row be removed from it?
If it becomes invalid what advise is there to not have to keep re-querying the database (or at least not recompile the statement each time)?
If the cursor is still valid but not updated, would be the best way to ensure the user cannot return to this row?
Are there any better solutions to this problem?
Just build a list of item IDs to be deleted. Once the user operation is finished, you can delete the whole lot of them in a single step.
You can use MatrixCursor to do this:
newCursor = new MatrixCursor(new String[] {col1, col2, col3}); // col names
mCursor.moveToPosition(-1); // your Cursor
while (mCursor.moveToNext()) {
if (<any condition>) {
newCursor.addRow(indicationNames.rows(mCursor));
}
}
mCursor = newCursor ;
By this way you have your cursor updated without affecting the database.

choosing between requery or firing the query again in SQLite

i have been using a SQLite database, Theres a situation where i have a list which displays all the "name" field data of a table "table1". Now i have a button to insert data in "table1". The list is populated using a simple cursor adapter which is passed a cursor "cursor1" populated with the data. "cursor1" is prepared using the SQLite query - "SELECT * FROM table1". Now the moment i insert data, i need to update the list too.
My question is-
will the Adapter sense the database change automatically (i guess not)?
using cursor1.requery() is correct or should i use cursor1 = db.query("table1", null, null, null, null, null, null);
It would be helpful if you can throw some light on which 1 is better and in which situation. Coz for the situation which i explained above, the requery() command is not giving a valid result while the later 1 works fine. still cant understand what the problem could be.
will the Adapter sense the database
change automatically (i guess not)?
No, the Adapter will not sense the database change automatically.
using cursor1.requery() is correct or
should i use cursor1 =
db.query("table1", null, null, null,
null, null, null);
Use requery(). Here is a sample project from one of my books demonstrating the technique.

Categories

Resources