I am having an odd problem deleting rows from a sqlite database. The first time I try deleting a row, it seems to work fine. However, anytime thereafter, I get no errors, it simply does not remove the selected row. If I uninstall the app and re-run it from eclipse (I have my tablet hooked up to my pc for testing) then the first delete works again.
Here is the code that I am using to populate a Gallery View from my database
Cursor cursor = _garmentAdapter.fetchAllLooks();
cursor.moveToLast();
final ArrayList<Bitmap> al = new ArrayList<Bitmap>();
_labels=new ArrayList<String>();
int totalGarments=0;
for(int i=cursor.getCount()-1; i>=0; i--) {
totalGarments++;
Bitmap bd=BitmapFactory.decodeFile(cursor.getString(3));
String label=cursor.getString(1);
al.add(bd);
_labels.add(label);
cursor.moveToPrevious();
}
Toast.makeText(BrowseLooks.this, "ITEMS=="+totalGarments, Toast.LENGTH_SHORT).show();
This toast message is displaying the number of items on screen. For example, if I create 3 items, then delete 1, it shows 2 on screen and the toast says ITEMS==2. However, if I delete another one, I still have 2 items on screen and ITEMS==2. So it seems the cursor is working correctly, but the database is not.
Here is the code for the delete row in the database:
return mDb.delete(LOOKS_TABLE, KEY_ROWID+"="+rowId, null)>0;
I have also logged rowId as being correct when mDb is called.
Once again, I am not getting any errors, the code is just not working. Any help would be very much appreciated.
Try this
db.delete(LOOKS_TABLE, KEY_ROWID+ " = ?",
new String[] { String.valueOf(rowId) });
I have found the answer to my problem. I did not fully understand the autoincrement of the sqlite database. Because of that, I was deleting rows that were already empty. The way the database increments is to create an entry higher than all previous entries not just the current highest entry. Therefore, the indexes of my on-screen items did not correspond to the indexes in my database table.
Related
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.
I have a database with 4 columns. Everything works fine except for the fact that random rows remain inaccessible. I cannot seem to update or delete them. I've used the right code:
DELETION CODE:
boolean deleted=db.delete(TABLE_NAME, KEY_BLAH + "=" + alarm, null) > 0;
CODE FOR UPDATE:
db.update(TABLE_NAME, args, KEY_BLAH + "=" + blah, null)
The deletion code returns false and the update code returns 0 for some rows, which are arbitrary. The rows are implemented into a ListView. Any changes on the ListView elements should be reflected in the SQLite Database. Most of the times the code works. It doesn't seem to work for random rows at random points though. I do not think this is SDK related. I've tried it on ICS, GB and JB.
I've also tried deleting the row and inserting it. Obviously this wouldn't work because my delete statement doesn't seem to work. The logic for this was, if the update wasn't possible it would delete the row and insert the row with the same row id and different data. So, the deleted variable was the condition for an if-block which didn't get executed.
EDIT
Example:
1 1414 000 off
When I click on a few buttons in the list item.
It should become
1 1414 064 off
Now, this works most of the times except for some random rows as I said before.
If you (indirectly) execute an SQL statement like this:
UPDATE MyTable SET x = '064' WHERE blah = 1414
then the values in the blah column are compared with the number 1414.
When using strings in SQL statements, you should always use parameters to avoid formatting problems like this (and SQL injection attacks):
db.update(TABLE_NAME, args, KEY_BLAH + "= ?", new String[] { blah })
So imagine this is a quick mockup of my database:
The items from the database are presented to the user per list, each list being displayed on a new fragment, which are displayed on a viewpager. So let's say in this hypotetical case, there would be two fragments on the viewpager, first fragment would display first_list and second fragment would display second_list. Here's the code for that query:
public static Cursor getListItems (final Context context, String listName) {
if (mDatabase == null || !mDatabase.isOpen())
open(context); //This gets the writable db.
String where = LIST_NAME + " = '" + listName + "'";
return mDatabase.query(TABLE_LIST_ITEMS, PROJECTION_LIST_ITEMS,
where, null, null, null, SORT_ORDER);
}
Where SORT_ORDER is order_in_list, this works well, to begin with.
Now, the listviews are re-arrangeable using a public library, which attempts to allow the user to control the order of the items in each list. Here's where I am having issues, there is no add(int index, Object object) for the cursor, or some other easy way to manage the sorting. I first thought I could simply call mDatabase.update() to change the value for order_in_list but that works, but the results are not as intended. For example, user drags item two to position zero, remeber: zero-index values, we would now have two items with order_in_list as zero. And although I can call mDatabase.update() on item one to update his position to one, imagine how much work that'd be to handle several items on a well-formed database.
Does anyone have any good suggestions on how I could work this out? I thought I had been clever by adding the extra col for sorting purposes :(
INB4:
Yes, I Know arrays handle this well. But the database doesn't only store 4 cols, it has many more fields. Populating arrays each time from the database would be a waste of time and effort. And I would, anyways, have to write back to the database when the app is closed.
EDIT So I changed the listview to only display one String of text, and further columns upon actual clicking on the item (and therefore displaying a new fragment with the specified list item data). This allowed me to simply keep an ArrayAdapter which easily handles the drag and drop. During onStop, I update the reference only if there was a change that required to be saved:
#Override
public void onStop() {
if (updateDbOnExit) {
//Update rows on database.
for (int i = 0; i < items.size(); i++) {
//Set the order in list be the actual order on the array.
Constants.LogMessage("Updating db content");
DbManager.moveListItemTo(getActivity(), items.get(i), i);
}
updateDbOnExit = false;
}
super.onStop();
}
Where MoveListItemTo updates the value for order_in_list:
public static void moveTaskItemTo (final Context context, String item, int to) {
if (mDatabase == null || !mDatabase.isOpen())
open(context);
String where = COL_CONTENT + " = '" + item+ "'";
ContentValues mContentValues = new ContentValues();
mContentValues.put(ORDER_IN_LIST, to);
int rows = mDatabase.update(TABLE_LIST_ITEMS, mContentValues, where, null);
Constants.LogMessage(rows + " row updated. Item moved to position: " + to);
close();
}
That will work for now. However, I am still interested on knowing if there is an alternate way, especially when for example, the adapter is using data from more than one column on the database, and is therefore required to use a CusorAdapter and not a regular ArrayAdapter, which in turn requires the Database itself to update upon each Drag and Drop to reflect the change on the UI via cursorAdapter.swapCursor(). As stated, updating ALL of the items on a database upon each drag (which realistically doesn´t happen that often btw), is expensive, updating only Two rows, would be a saner choice.
I just meant I wanted a more effective way to update the fields in the db, rather than manually updating each and every single row
Make the user-specified-order column a decimal, not an integer. Then you need to update only the moved row(s).
Allow negative numbers.
0.00 cat
1.00 aardvark
2.00 wolf
3.00 dog
If "dog" is dragged above "wolf" then "dog" becomes 1.50 and no need to change other rows. If "aardvark" is dragged above "cat" (special case -- prepending to list rather than inserting between rows) then subtract 1 from the topmost value, and "aardvark" becomes -1.00.
This will require you to know the values of the adjacent rows, but you won't have to update them. Only the moved row's value must change.
I would suggest that you have an additional column, user_specified_order which would represent the user's reordering of the rows in the UI via drag-drop.
You must update each row when its user_specified_order value is invalidated by the drag-drop repositioning. When to persist that value is up to you -- either at the "end" of the user's manipulations, however that be defined (e.g. click on Save button) or after each drag/drop if there is no clearcut UI indicator of "end of manipulation".
EDIT: ContenProvider in Android:
Android - Can you update a Cursor for SQLite results?
Android SQLite transactions:
Android Database Transaction
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.
I think it's kinda easy one but still I'm new to android programming so please have patience. I want to know how can I get the number of records (rows) in a specific table in my db. I need this so I can create a loop to go through every record and add each one of it to the specific Array and display it later on. This is the source:
db.openDataBase(); // open connection with db
Cursor c = db.getTitle(5); // loop here through db, right now I'm fetching only one record
startManagingCursor(c);
//adding areas to the list here
Area o1 = new Area();
o1.setOrderName(c.getString(1) + c.getString(2));
m_areas.add(o1);
db.close();
Does anyone can help me with this please? Thx in advance!
SELECT COUNT(*) FROM tablename
To get the number of rows in the cursor, use getCount.
To get the amount of total rows in a table, either use reinierposts solution, or do a select which select all rows in the table and get the count from the cursor. I'm guessing his solution is quicker though unless you actually need all the rows in the table.
Such a query would be:
SELECT * FROM footable;
You don't really need to get a count of how many first; instead, create a db.getTitles() function that returns all of the rows and returns a Cursor, then loop over the Cursor. Right now you probably have a query that looks something like SELECT ColumnA, ColumnB FROM Titles WHERE id = 5; just copy the function, remove the parameter and take off the WHERE clause so it looks like just SELECT ColumnA, ColumnB FROM Titles.
Then your code would look something like this:
db.openDataBase(); // open connection with db
Cursor c = db.getTitles();
startManagingCursor(c);
//adding areas to the list here
if (c != null && c.moveToFirst()) {
do {
Area o1 = new Area();
o1.setOrderName(c.getString(1) + c.getString(2));
m_areas.add(o1);
} while (c.next());
}
db.close();
We check if the function returned a cursor at all, then move to the beginning of the cursor and start looping, going to the next item each time through. For more information on the Cursor interface see the API here, or to learn more about database access and related design practices better in general I suggest going through the Notepad tutorial.