Unable to update a particular column on SQLite - android

I've been trying to update on of my column in my database named COLUMN_NAME_PERIOD_END but it doesn't seem to be able to.
String[] endDate = new String[1];
endDate[0] = paraPeriodDetailsPojoObj.getPeriodEndDate();
Log.d("PeriodEnd.onClick()", "Date: " + endDate[0]);
/*UPDATE table_name
SET column1=value, column2=value2,...
WHERE some_column=some_value
*/
sqliteDatabase.update(DBStorage.TABLE_NAME_PERIODSTART, contentValues, DBStorage.COLUMN_NAME_PERIOD_END+"=?", endDate);
No error messages were displayed so I suppose it is my update statement that is having errors. :(

From the docs:
update(String table, ContentValues values, String whereClause, String[] whereArgs)
So, you are putting the array of contentValues (which you don't show, so the problem could be there) into the table defined by TABLE_NAME_PERIODSTART, and selecting which record to update by searching the column defined by COLUMN_NAME_PERIOD_END which must equal endDate.
The way I read your question title I'm under the impression you actually want to update the COLUMN_NAME_PERIOD_END column with the endDate... if that's the case your SQL is incorrect.
Otherwise, some possibilities that leap to mind to look for are:
1) Constraints... do you have a not null field defined and you are trying to update with a null?
2) Your date format from the program is differing from the one in the database
3) There is no matching record for the endDate you are searching for in the DB

Related

How to update a value in a column with existing value in SQLite?

I'm trying to update a table in SQLite android. I have a column called 'quantity' which stores qty of some items, say item1, item2 ...
Now when I purchase item1, I'd definitely want to 'add' the purchased qty to an existing qty of item1.
I searched the web but couldn't find a solution, hence asking this.
My simple code's below:
// This method is used to 'UPDATE' the table 'stock'.
// This method will be used by two fragments,
// 'sale' and 'purchase' fragments.
public int updateData(String cigaretteName,int quantity, int cost, int totalCost) {
// Accessing the database with writable functionality so it can be updated.
SQLiteDatabase db = this.getWritableDatabase();
// Creating content values object to put the new values in existing rows with old values.
ContentValues contentValues = new ContentValues();
contentValues.put(StockEntry.COLUMN_QUANTITY, (StockEntry.COLUMN_QUANTITY + quantity));
contentValues.put(StockEntry.COLUMN_COST, cost);
contentValues.put(StockEntry.COLUMN_TOTAL_COST, totalCost);
// Which row to update, based on the cigarette name.
String selection = StockEntry.COLUMN_CIGARETTES_NAME + " LIKE ?";
String[] selectionArgs = {cigaretteName};
// Updating the table with the new values and then returning the number of rows affected.
return db.update(StockEntry.TABLE_NAME, contentValues, selection, selectionArgs);
}
This isn't working at all, now it doesn't even update the column/row.
contentValues.put(StockEntry.COLUMN_QUANTITY, (StockEntry.COLUMN_QUANTITY + quantity));
Do help guys!
I would suggest simple approach to overcome these kind of SQLite related issues.
Use SQLite Manager which is plugin for FireFox browser
Download from https://addons.mozilla.org/en-US/firefox/addon/sqlite-manager/
Create your dummy database there
Perform your CRUD operations here
Once everything working fine in SQLite Manager then use same query inside your project.
Above way will save your development time as well as testing.

Sqlite: SqliteDatabase.delete() vs a raw query

Conclusion: Android's database APIs work but the documentation is horribly incomplete.
I have recently run into a brain wrecking situation due to the flexibility Sqlite provides by not forcing you to specify the data type when creating the table. The problem was my mindset that assumed that every data type would be a general character sequence if not specified and therefore the way to talk to database is through java.lang.String.
But you can't blame me either when you see methods like the below:
int delete (String table,
String whereClause,
String[] whereArgs)
in the SqlDatabase class from Android docs.
I have a table consisting of Phone No(that I stored as java.lang.String) and Timestamp as a long field. When I tried deleting a record using this method, it just never got deleted despite countless debugging.
I checked everything and query was alright and table is existent and all the checklist until by chance, I discovered that removing the '' around the timestamp while querying in a raw manner instead of using the above method yields a successful deletion, something like this:
DELETE FROM messages_records_table WHERE messageTimestamp = 1508494606000;
instead of the following:
DELETE FROM messages_records_table WHERE messageTimestamp = '1508494606000';
or,
DELETE FROM messages_records_table WHERE messageTimestamp = "1508494606000";
Phone No isn't a problem; it's the timestamp that was creating the problem in INSERTION/DELETION
So, I tried running a raw deletion query with quotes removed(that are required with a string/varchar type) and it yielded successful deletion. I used the following method for this:
db.execSQL(String sql, Object[] whereArgs)
The key thing to notice here is that Object[] is different from String[] when compared to delete(). I passed a Long to Object to make it work but passing a Long.toString() in delete() seems to be useless.
So my question is, Is my analysis correct and delete() API is basically useless or have I missed some bigger picture..after all, it's provided by Android team carefully?
SQLite supports multiple data types; and while column types are not strictly enforced, values might be automatically converted in some cases (this is called affinity).
When your values are stored as numbers, you should access them as numbers, not as strings.
The Android database API does not allow you to use parameter types other than strings in most functions. This is a horrible design bug.
To search for a number, either use execSQL(), which allows you to use number parameters, or convert the string value back into a number:
db.delete(..., "timestamp = CAST(? AS NUMBER)",
new String[]{ String.valueOf(ts) });
The problem was my mindset that assumed that every data type would be
a general character sequence if not specified and therefore the way to
talk to database is through java.lang.String.
I think that's the real issue.
If you specify no type e.g.
CREATE TABLE mytable (col1,col2,col3)
Then according to Determination of Column Affinity(3.1) rule 3:-
3) If the declared type for a column contains the string "BLOB" or if no
type is specified then the column has affinity BLOB.
And then according to Section 3
A column with affinity BLOB does not prefer one storage class over
another and no attempt is made to coerce data from one storage class
into another.
I've personally never had an issue with delete. However I do have a tendency to always delete according to rowid.
Here's a working example usage that shows that delete isn't useless and is deleting according to a long. However the columns are all of type INTEGER :-
int pudeletes;
int sldeletes;
int rdeletes;
int pdeletes;
if(doesProductExist(productid)) {
// if not in a transaction then begin a transaction
if(!intransaction) {
db.beginTransaction();
}
String whereargs[] = { Long.toString(productid)};
// Delete ProductUsage rows that use this product
pudeletes = db.delete(
DBProductusageTableConstants.PRODUCTUSAGE_TABLE,
DBProductusageTableConstants.PRODUCTUSAGE_PRODUCTREF_COL +
" = ?",
whereargs
);
// Delete ShopList rows that use this product
sldeletes = db.delete(
DBShopListTableConstants.SHOPLIST_TABLE,
DBShopListTableConstants.SHOPLIST_PRODUCTREF_COL +
" = ?",
whereargs
);
// Delete Rules rows that use this product
rdeletes = db.delete(
DBRulesTableConstants.RULES_TABLE,
DBRulesTableConstants.RULES_PRODUCTREF_COL +
" = ?",
whereargs
);
// Delete the Product
pdeletes = db.delete(
DBProductsTableConstants.PRODUCTS_TABLE,
DBProductsTableConstants.PRODUCTS_ID_COL +
" = ?",
whereargs
);
// if originally not in a transaction then as one was started
// complete and end the transaction
if(!intransaction) {
db.setTransactionSuccessful();
db.endTransaction();
}
}

How to update android database when fresh JSON content arieves?

Could someone suggest me a way on how to update my apps SQLite database when the content of the parsed JSON file is changed?
I am having a hard time finding the right solution, now I have to clear the cache before the app starts, but the end user obviously won't do that.
I asume changing the table version is not suitable for frequent updates (hourly).
Thanks!
As #KenWolf mentioned this documentation in the comments.
Update a Database:
When you need to modify a subset of your database values, use the update() method.
Updating the table combines the content values syntax of insert() with the where syntax of delete().
SQLiteDatabase db = mDbHelper.getWritableDatabase();
// New value for one column
ContentValues values = new ContentValues();
values.put(FeedEntry.COLUMN_NAME_TITLE, title);
// Which row to update, based on the title
String selection = FeedEntry.COLUMN_NAME_TITLE + " LIKE ?";
String[] selectionArgs = { "MyTitle" };
int count = db.update(
FeedReaderDbHelper.FeedEntry.TABLE_NAME,
values,
selection,
selectionArgs);
Change your database version by incrementing by 1 from current value.
It will make possible of updation.

android update database column based on the current column value

In android, SQLiteDatabase has a update function
update(String table, ContentValues values, String whereClause, String[] whereArgs)
new values in put in values
If I want to update a column A by adding one to it, how should I prepare the ContentValues values variable? I don't think the following would work.
cv.put("A", "A" + 1);
I can sure run execSQL with raw sql, but it does not return num of row updated
If you'd execute a raw query, something like this should work to increment the current value in the column:
UPDATE table_name SET column_a = column_a + 1 WHERE _id = 1
(where 1 is just an example to illustrate how to apply it to a specific row)
The same probably wouldn't work with ContentValues, since (as the name indicates) it takes the values to set the column to. That means it needs to have been evaluated before building the ContentValues, whereas with a raw query the value isn't evaluated until the query actually runs on the database.
You can of course retrieve the current value first and then increment that accordingly when issuing an update; that requires a select query first. Quite commonly though, you're working with objects in Java, where the column value for a row is bound up to a member field of the object. If you've got a setup like that, then you probably already have the current value at the moment you want to run an update query.
As such, it would just look somewhat like:
SomeObject object = ...;
cv.put("column_a", object.getSomeValue() + 1);
(where I'm assuming object.getSomeValue() will return an int)
// edit: here's some more examples for the raw query approach:
SQLite - increase value by a certain number
// edit2: You've edited your original question and added:
I can sure run execSQL with raw sql, but it does not return num of
row updated
If knowing how many rows the query changed is a must, then you can potentially leverage the changes() function. It still means you're going to have to run a second query though.
SELECT changes() FROM table_name
The docs say:
The changes() function returns the number of database rows that were
changed or inserted or deleted by the most recently completed INSERT,
DELETE, or UPDATE statement, exclusive of statements in lower-level
triggers. The changes() SQL function is a wrapper around the
sqlite3_changes() C/C++ function and hence follows the same rules for
counting changes.
Alternatively, you could look into the rawQuery() method that takes an SQL statement and returns the result as a Cursor. Not sure if it that even works for an update query, or whether the result would be anything sensible, but if you're really lucky, you may find that Cursor.getCount() gives you the number of affected rows.
To expand upon #MH's solution, there actually is a way to do a raw update AND get back the number of rows updated (because I'm doing the same thing in one of my projects). You have to use a compiled SQLiteStatement and then call the method executeUpdateDelete(). From the documentation:
public int executeUpdateDelete ()
Execute this SQL statement, if the the number of rows affected by execution of this SQL statement is of any importance to the caller - for example, UPDATE / DELETE SQL statements.
Returns
the number of rows affected by this SQL statement execution.
See the following sample code where I add a new column to my table and then update each column similarly to how you were asking:
db.beginTransaction();
try {
db.execSQL("ALTER TABLE " + TABLE_NAME + " ADD COLUMN "
+ COLUMN_NAME_LOCALTIME + " INTEGER");
String stmtString = "UPDATE " + TABLE_NAME + " SET "
+ COLUMN_NAME_LOCALTIME + "="
+ COLUMN_NAME_TIME + "+ (" + tzOffset + ")";
SQLiteStatement sqlStmt = db.compileStatement(stmtString);
int rows = sqlStmt.executeUpdateDelete();
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
I'm using a transaction here because in case I add the new column but CANNOT update the values, I want everything to rollback so I can attempt something else.

When I update a column an duplicate column is created in DB for my android app

I am creating my first android app, and now struck on a weird issue
Here is the situation:
The user can enter a numeric value for any given date.
Issue:
So when user tries to give another score for the same date, as we all know the app should over write the old value and update the new value the user just gave.
So I have a update method that gets the rowId and overwrites old values by new. but what's happening in my table is scary. When I update a numeric value for the same date say 6/6/2011. it creates another record, now I have 2 entries on same date one is old and one is new. and then when i do it to some other date say 6/7/2011(like give a value for a date and then update it) the duplicate column created for 6/6/2011 is gone and a duplicate column is created for 6/7/2011.
updateValue(...){
ContentValues args = new ContentValues();
args.put(KEY_DATESTAMP_SUBTABLE, day);
args.put(KEY_HABIT, habit);
args.put(KEY_USER_SCORE_SUBTABLE, userScore);
args.put(KEY_CALCULATED_SCORE_SUBTABLE,
calculateCompoundScore(scoringMethod, userScore, importance));
String whereClause = KEY_ROWID + "=" + rowId;
return mDb.update(SCORE_TABLE, args, whereClause, null) > 0;
}
can anybody explain me this behavior!!!!
I edited and added the code:
edited:
I found the problem, it is a dumb mistake, the rowID is the row id of a different table, so every time i delete using that it gives me wild results. It is my bad..BUt #Alex idea helped me to figure it out as for update as he said, i deleted first and then inserted, while doing this i found it is deleting some other row.
Thanks
Like gopal said, would be nice to see some code.
Regardless, couldn't you just delete the old entry and add a completely new one into the table?

Categories

Resources