Android problem using built in SQLiteDatabase execSQL to update function - android

I have the following code to open a database on the SDCARD and then update a value. If I run the code as is, it will generally run through without throwing an error but nothing gets updated.
If I single step through each line, it works perfectly. I have also tried adding SystemClock.Sleep(2000) in between each statement. Still, it does not run properly unless I single step through this section.
Any ideas?
SQLiteDatabase db = openOrCreateDatabase( sdDIR + "/DBNAME.db", SQLiteDatabase.CREATE_IF_NECESSARY, null);
db.execSQL("UPDATE tableName SET value='" + newValue + "' WHERE name='field_name';");
db.close();

From the Android SQLiteDatabase documentation:
public void execSQL (String sql, Object[] bindArgs)
Execute a single SQL statement that is NOT a SELECT/INSERT/UPDATE/DELETE.
You need to use update() or rawQuery().

Related

Why cursorObject.moveToFirst() is required on updating my database table value

I had a problem with updating of a column's value at a particular row. I had written
Cursor c = mDb.rawQuery("UPDATE "+book+" SET footnotes='" + note + "' WHERE chapter="+chapter+" and verse="+verse+"", null);
c.close();
But on adding c.moveToFirst() it worked. Why is that?
Cursor c = mDb.rawQuery("UPDATE "+book+" SET footnotes='" + note + "' WHERE chapter="+chapter+" and verse="+verse+"", null);
c.moveToFirst();
c.close();
Why is c.moveToFirst() necessary here, any particular reason?
There is an explation for c.moveToFirst()
(What is The use of moveToFirst () in SQLite Cursors) which briefly suggests that using c.moveToFirst() does two things
allows you to test whether the query returned an empty set
moves the cursor to the first result
But how does the above two things help in updation?
Think of rawQuery() as a wrapper for the C library sqlite3_prepare_v2() that compiles the SQL but does not run it, while think of moveTo..() as a wrapper for sqlite3_step() that is required for actually executing the prepared statement.
Related: What is the correct way to do inserts/updates/deletes in Android SQLiteDatabase using a query string?

Sqlite database update error

I'm trying to run an update statement. The method located in database class is below.
I'm passing the variables to the method correctly and the code that runs without exception. However when I LogCat, the column value does not change. I don't know what or where the problem is...can someone please help me?
public Cursor updateStatus(int ID,String status) {
return database.rawQuery("Update events set status= '"+status+"' where _id=" + ID, null);
}
Use execSQL() instead of rawQuery() to execute SQL like this.
rawQuery() alone just compiles the SQL but does not run it.

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.

slight misunderstanding with sqlite database in android

i created a database with 6 columns and i have a create and update method in my class that takes 6 parameters/arguments which represent these columns. my problem is that, anytime i try to update or create the database without using all 6 arguments (setting some to null), i get an error "constraint failed". this is most particular with the update method.
any ideas how i can get around this? because sometimes i don't want to fill all columns. I have removed the "text not null" constraint when creating the database. Thank you.
You're going to want to use the ContentValues to achieve this. Heres a quick demo.
My function
public boolean updateStuff(int id,ContentValues args) {
return mDb.update(TableName, args, _id_col + "=" + id, null) > 0;
}
And to call it. Note you can put as many ContentValues as you need
ContentValues initValues = new ContentValues();
initValues.put(col_key,col_value);
Edit:
mDB is a SQLiteDatabase

How to import sqlite file into my project?

I am making an sqlight using eclipse outside the android project
what should I add into my android manifest in order to make it work?
thank you Mathias, lets take this q to another project who generate a SQL file using java
assuming this. How can I set the SQLiteDatabase.NO_LOCALIZED_COLLATORS flag when calling SQLiteDatabase.openDatabase()?
my code over there is
Class.forName("org.sqlite.JDBC");
Connection conn = DriverManager.getConnection("jdbc:sqlite:test.db");
/*
*some code
*/
Statement stat = conn.createStatement();
stat.executeUpdate("drop table if exists "+TABLE_NAME+";");
//stat.executeUpdate("create table "+TABLE_NAME+" (name, occupation);");
stat.executeUpdate("create table "+TABLE_NAME+" ("+VALUE+","+TYPE+","+LETTER+");");
PreparedStatement prep = conn.prepareStatement(
"insert into "+TABLE_NAME+" values (?, ?,?);");
Even when I use:
db = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS);
when I use the query :
String s = "Israel";
Cursor cursor = db.query(TABLE_NAME, new String[] {VALUE}
,VALUE + " like " + "'%" + s +"%'", null, null, null, null);
I get an exception .
You don't need to add anything special into the android manifest. You can open the database from anywhere, i.e. also from your sdcard or else. Otherwise, A common place to put the database is in to the assets folder of your application.
When you create the db outside the android project, just make sure you either create the metadata table (as mentioned in the Android docs) or set the SQLiteDatabase.NO_LOCALIZED_COLLATORS flag when calling SQLiteDatabase.openDatabase(). Also you should note that the primary key in all tables is _id. These are the most important things to consider when creating a new DB.
Also helpful regarding the metadata-table might be:
What is the android_metadata table?
No such table android_metadata, what's the problem?
Helpful blog:
http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/

Categories

Resources