Sqlite not updating rows - android

Hi I'm trying to update some rows incrementing a value in an int field but it doesn't work.
Here my snippet of code:
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables("TICKET");
String[] proj = new String[]{ "TICKET","NUMERO_ARTICOLO","QUANTITA","COMMESSA_IN","CODICE_SQUADRA"};
try{
Cursor cursor = queryBuilder.query(sqlDB, proj, selection, null, null, null, null);
sqlDB.beginTransaction();
cursor.moveToFirst();
while (cursor.moveToNext()){
String query = "UPDATE MATERIALE "
+ " SET RIMANENTE = RIMANENTE - " + cursor.getString(cursor.getColumnIndex("QUANTITA"))
+ " WHERE NUMERO_ARTICOLO = '"+cursor.getString(cursor.getColumnIndex("NUMERO_ARTICOLO"))+"'"
+" AND COMMESSA = '"+cursor.getString(cursor.getColumnIndex("COMMESSA_IN"))+"' "
+" AND CODICE_SQUADRA = '"+cursor.getString(cursor.getColumnIndex("CODICE_SQUADRA"))+"' ";
Log.d("update","Query: "+query);
sqlDB.rawQuery(query, null);
}
rowsUpdated = sqlDB.update("TICKET", values, selection, null);
sqlDB.setTransactionSuccessful();
Log.d("update","Aggiornate "+rowsUpdated+" righe");
sqlDB.endTransaction();
}catch (Exception e) {
e.printStackTrace();
}
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
getContext().getContentResolver().notifyChange(CONTENT_URI, null);
return rowsUpdated;
Last query is working
rowsUpdated = sqlDB.update("TICKET", values, selection, null);
but the while cycle is not working.
What I do wrong? Maybe the UPDATE SET RIMANENTE = RIMANENTE - " + cursor.getString(cursor.getColumnIndex("QUANTITA"))
I want the cycle (while) and the last update in the same transaction.

Sqlite uses file-based locking while you are inserting-updating or selecting the rows from database. This means when you are fetching the records from database using Select query and until the cursor with that select statement is not closed you can not insert update or delete in mean time.
So you should close the cursor and then use execSQL in place of rawQuery to fire update
try
{
Cursor cursor = queryBuilder.query(sqlDB, proj, selection, null, null, null, null);
//sqlDB.beginTransaction();
List<String> updateSql = new ArrayList<String>();
try
{
cursor.moveToFirst();
while (cursor.moveToNext())
{
updateSql.add( "UPDATE MATERIALE "
+ " SET RIMANENTE = RIMANENTE - " + cursor.getString(cursor.getColumnIndex("QUANTITA"))
+ " WHERE NUMERO_ARTICOLO = '"+cursor.getString(cursor.getColumnIndex("NUMERO_ARTICOLO"))+"'"
+" AND COMMESSA = '"+cursor.getString(cursor.getColumnIndex("COMMESSA_IN"))+"' "
+" AND CODICE_SQUADRA = '"+cursor.getString(cursor.getColumnIndex("CODICE_SQUADRA"))+"' ");
Log.d("update","Query: "+query);
}
}
finally
{
cursor.close();
}
try
{
sqlDB.beginTransaction();
for (String query : updateSql)
{
sqlDB.execSQL(query, null); //Here it should be execSQL instead of rawQuery
}
rowsUpdated = sqlDB.update("TICKET", values, selection, null);
sqlDB.setTransactionSuccessful();
Log.d("update","Aggiornate "+rowsUpdated+" righe");
}
finally
{
sqlDB.endTransaction();
}
}
catch (Exception e)
{
e.printStackTrace();
}
EDIT If I read documentation it is clearly mentioned that
For UPDATE statements, use any of the following instead.
update(String, ContentValues, String, String[])
updateWithOnConflict(String, ContentValues, String, String[], int)

You'd better use SQL facilities to accomplish this task:
try {
sqlDB.execSQL("UPDATE TICKET SET RIMANENTE = RIMANENTE - QUANTITA");
} catch (Exception e) {
e.printStackTrace();
}
This will, in a single statement - so, in a single transaction also - subtract QUANTITA to RIMANENTE in all rows from table TICKET.
EDIT:
UPDATE TICKET SET RIMANENTE = RIMANENTE - QUANTITA WHERE QUANTITA IS NOT NULL
is preferable, because if QUANITTA is not defined, i.e. NULL, RIMANENTE will be nulled. WHERE clause prevents such from happen.

Related

How to use call log for copy incoming number in android

I just want to copy the incoming number and paste it to a text box. How can I do that?
Use a cursor to get any call log information you want.
String[] projection = {android.provider.CallLog.Calls._ID,
android.provider.CallLog.Calls.NUMBER,
CallLog.Calls.TYPE, CallLog.Calls.DATE};
final Cursor cursor = getActivity().getContentResolver().query(
android.provider.CallLog.Calls.CONTENT_URI, projection,
"type = " + CallLog.Calls.INCOMING_TYPE, null,
android.provider.CallLog.Calls.DATE + " DESC" + " LIMIT 200");
The cursor will result the number and time of call.
if (cursor.moveToFirst()) {
do {
try {
String number = cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER));
String date = cursor.getString(cursor.getColumnIndex(CallLog.Calls.DATE));
// Do anything with number and name
} catch (Exception e) {
}
} while (cursor.moveToNext());
}
cursor.close();

Android sqlite how to check if a record exists

I would like to check whether a record exists or not.
Here is what I've tried:
MainActivity.class
public void onTextChanged(CharSequence s, int start, int before, int count) {
System.out.println("Ontext changed " + new String(s.toString()));
strDocumentFrom = s.toString();
if(s.toString().isEmpty()){
} else {
try{
strTransactionDate = dbHelper.getTransactionDateByDocumentNumber(strDocumentFrom);
//strTotalAmount = dbHelper.getTotalAmountByDocumentNumber(strDocumentFrom);
//strVan = dbHelper.getVanByDocumentNumber(strDocumentFrom);
//etTransactionDate.setText(strTransactionDate);
//etTotalAmount.setText(strTotalAmount);
//Log.d("Van", "" + strVan);
//etVan.setText(strVan);
} catch (SQLiteException e) {
e.printStackTrace();
Toast.makeText(ReceivingStocksHeader.this,
"Document number does not exist.", Toast.LENGTH_SHORT).show();
}
}
DBHelper.class
// TODO DISPLAYING RECORDS TO TRANSRCVHEADER
public String getTransactionDateByDocumentNumber(String strDocumentNumber){
String[] columns = new String[]{KEY_TRANSACTIONDATE};
Cursor c = myDataBase.query(TBL_INTRANS,
columns, null,
null, null, null, null, null);
if(c != null){
c.moveToFirst();
String date = c.getString(0);
return date;
} else {
Log.d("Error", "No record exists");
}
return null;
}
But it doesn't get it to the catch block to display the toast.
What am I doing wrong in here?
public static boolean CheckIsDataAlreadyInDBorNot(String TableName,
String dbfield, String fieldValue) {
SQLiteDatabase sqldb = EGLifeStyleApplication.sqLiteDatabase;
String Query = "Select * from " + TableName + " where " + dbfield + " = " + fieldValue;
Cursor cursor = sqldb.rawQuery(Query, null);
if(cursor.getCount() <= 0){
cursor.close();
return false;
}
cursor.close();
return true;
}
I hope this is useful to you...
This function returns true if record already exists in db. Otherwise returns false.
These are all good answers, however many forget to close the cursor and database. If you don't close the cursor or database you may run in to memory leaks.
Additionally: You can get an error when searching by String that contains non alpha/numeric characters. For example: "1a5f9ea3-ec4b-406b-a567-e6927640db40". Those dashes (-) will cause an unrecognized token error. You can overcome this by putting the string in an array. So make it a habit to query like this:
public boolean hasObject(String id) {
SQLiteDatabase db = getWritableDatabase();
String selectString = "SELECT * FROM " + _TABLE + " WHERE " + _ID + " =?";
// Add the String you are searching by here.
// Put it in an array to avoid an unrecognized token error
Cursor cursor = db.rawQuery(selectString, new String[] {id});
boolean hasObject = false;
if(cursor.moveToFirst()){
hasObject = true;
//region if you had multiple records to check for, use this region.
int count = 0;
while(cursor.moveToNext()){
count++;
}
//here, count is records found
Log.d(TAG, String.format("%d records found", count));
//endregion
}
cursor.close(); // Dont forget to close your cursor
db.close(); //AND your Database!
return hasObject;
}
Raw queries are more vulnerable to SQL Injection. I will suggest using query() method instead.
public boolean Exists(String searchItem) {
String[] columns = { COLUMN_NAME };
String selection = COLUMN_NAME + " =?";
String[] selectionArgs = { searchItem };
String limit = "1";
Cursor cursor = db.query(TABLE_NAME, columns, selection, selectionArgs, null, null, null, limit);
boolean exists = (cursor.getCount() > 0);
cursor.close();
return exists;
}
Source: here
SELECT EXISTS with LIMIT 1 is much faster.
Query Ex: SELECT EXISTS (SELECT * FROM table_name WHERE column='value' LIMIT 1);
Code Ex:
public boolean columnExists(String value) {
String sql = "SELECT EXISTS (SELECT * FROM table_name WHERE column='"+value+"' LIMIT 1)";
Cursor cursor = database.rawQuery(sql, null);
cursor.moveToFirst();
// cursor.getInt(0) is 1 if column with value exists
if (cursor.getInt(0) == 1) {
cursor.close();
return true;
} else {
cursor.close();
return false;
}
}
You can use SELECT EXISTS command and execute it for a cursor using a rawQuery,
from the documentation
The EXISTS operator always evaluates to one of the integer values 0
and 1. If executing the SELECT statement specified as the right-hand
operand of the EXISTS operator would return one or more rows, then the
EXISTS operator evaluates to 1. If executing the SELECT would return
no rows at all, then the EXISTS operator evaluates to 0.
I have tried all methods mentioned in this page, but only below method worked well for me.
Cursor c=db.rawQuery("SELECT * FROM user WHERE idno='"+txtID.getText()+"'", null);
if(c.moveToFirst())
{
showMessage("Error", "Record exist");
}
else
{
// Inserting record
}
One thing the top voted answer did not mention was that you need single quotes, 'like this', around your search value if it is a text value like so:
public boolean checkIfMyTitleExists(String title) {
String Query = "Select * from " + TABLE_NAME + " where " + COL1 + " = " + "'" + title + "'";
Cursor cursor = database.rawQuery(Query, null);
if(cursor.getCount() <= 0){
cursor.close();
return false;
}
cursor.close();
return true;
}
Otherwise, you will get a "SQL(query) error or missing database" error like I did without the single quotes around the title field.
If it is a numeric value, it does not need single quotes.
Refer to this SQL post for more details
SQLiteDatabase sqldb = MyProvider.db;
String Query = "Select * from " + TABLE_NAME ;
Cursor cursor = sqldb.rawQuery(Query, null);
cursor.moveToLast(); //if you not place this cursor.getCount() always give same integer (1) or current position of cursor.
if(cursor.getCount()<=0){
Log.v("tag","if 1 "+cursor.getCount());
return false;
}
Log.v("tag","2 else "+cursor.getCount());
return true;
if you not use cursor.moveToLast();
cursor.getCount() always give same integer (1) or current position of cursor.
Code :
private String[] allPushColumns = { MySQLiteHelper.COLUMN_PUSH_ID,
MySQLiteHelper.COLUMN_PUSH_TITLE, MySQLiteHelper.COLUMN_PUSH_CONTENT, MySQLiteHelper.COLUMN_PUSH_TIME,
MySQLiteHelper.COLUMN_PUSH_TYPE, MySQLiteHelper.COLUMN_PUSH_MSG_ID};
public boolean checkUniqueId(String msg_id){
Cursor cursor = database.query(MySQLiteHelper.TABLE_PUSH,
allPushColumns, MySQLiteHelper.COLUMN_PUSH_MSG_ID + "=?", new String [] { msg_id }, null, null, MySQLiteHelper.COLUMN_PUSH_ID +" DESC");
if(cursor.getCount() <= 0){
return false;
}
return true;
}
Here's a simple solution based on a combination of what dipali and Piyush Gupta posted:
public boolean dbHasData(String searchTable, String searchColumn, String searchKey) {
String query = "Select * from " + searchTable + " where " + searchColumn + " = ?";
return getReadableDatabase().rawQuery(query, new String[]{searchKey}).moveToFirst();
}
because of possible data leaks best solution via cursor:
Cursor cursor = null;
try {
cursor = .... some query (raw or not your choice)
return cursor.moveToNext();
} finally {
if (cursor != null) {
cursor.close();
}
}
1) From API KITKAT u can use resources try()
try (cursor = ...some query)
2) if u query against VARCHAR TYPE use '...' eg. COLUMN_NAME='string_to_search'
3) dont use moveToFirst() is used when you need to start iterating from beggining
4) avoid getCount() is expensive - it iterates over many records to count them. It doesn't return a stored variable. There may be some caching on a second call, but the first call doesn't know the answer until it is counted.
Try to use cursor.isNull method.
Example:
song.isFavorite = cursor.isNull(cursor.getColumnIndex("favorite"));
You can use like this:
String Query = "Select * from " + TABLE_NAME + " where " + Cust_id + " = " + cust_no;
Cursor cursorr = db.rawQuery(Query, null);
if(cursor.getCount() <= 0){
cursorr.close();
}
cursor.close();
private boolean checkDataExistOrNot(String columnName, String value) {
SQLiteDatabase sqLiteDatabase = getReadableDatabase();
String query = "SELECT * FROM" + TABLE_NAME + " WHERE " + columnName + " = " + value;
Cursor cursor = sqLiteDatabase.rawQuery(query, null);
if (cursor.getCount() <= 0) {
cursor.close();
return false; // return false if value not exists in database
}
cursor.close();
return true; // return true if value exists in database
}
I prefer to do it this way because it's fast and less expensive than other methods:
Cursor cursor = db.rawQuery("SELECT 1 FROM table WHERE condition = 1 LIMIT 1", null);
try {
if (cursor.moveToNext()) {
//Record exists
} else {
//Record doesn't exists
}
} finally {
cursor.close();
}
My version:
public boolean isTitleExists(String title, String type) {
int isExists = 0;
try {
String query = "SELECT EXISTS (SELECT 1 FROM titles WHERE title = ? and type = ?)";
PreparedStatement statement = connection.prepareStatement(query);
statement.setString(1, title);
statement.setString(2, type);
ResultSet rs = statement.executeQuery();
rs.next();
isExists = rs.getInt(1);
rs.close();
statement.close();
} catch (SQLException e) {
Common.console("isTitleExists error: " + e.getMessage());
}
return isExists == 1;
}

Android SQLite rawQuery() method

I created a table with three columns id, name and discipline.
I want to find the student name given the discipline.
Following is my method:
String findstudent(String disc){
SQLiteDatabase sqLiteDatabase = this.getReadableDatabase();
String find = "SELECT * FROM "+ TABLE_STUDENTS + " WHERE "+KEY_DISCIPLINE +" = " +disc ;
Cursor cursor = sqLiteDatabase.rawQuery(find,null);
cursor.moveToFirst();
String found =cursor.getString(1);
return found;
}
When I use it, the application stops working.
I am not sure. But, you can try this way
Cursor.moveToFirst();
do{
//get the data
String found =cursor.getString(cursor.getColumnIndexOrThrow("COLUMN NAME"));
}while(Cursor.moveNext);
Try the following code:
String find = "SELECT *<enter code here>
FROM "+ TABLE_STUDENTS + "
WHERE "+KEY_DISCIPLINE +" = '" + disc + "'" ;
Try this:
String findstudent(String disc){
Cursor cursor;
cursor = this.db.query(TABLE_STUDENTS,null, KEY_DISCIPLINE +" = "+ disc, null, null, null, null,null );
cursor.moveToFirst();
String found =cursor.getString(0);
return found;
}
Hope it Helps!!
public Cursor findstudent(String disc){
SQLiteDatabase sqLiteDatabase = this.getReadableDatabase();
String[] find = new String[]{ col1,col2,col3};//all fields in db in need
String order=col1;
Cursor c=db.query(TABLE_STUDENTS, find, KEY_DISCIPLINE +" = " +disc, null, null, null, order);
c.moveToFirst();
db.close();
return c;
}
In the activity include this:
DataBaseHandler db = new DataBaseHandler(this);
try {
Cursor c = db.displayName(your_disc);
startManagingCursor(c);
if (!c.moveToFirst()) {
System.out.println("!Move " + posnumber);
} else {
String idname = c.getString(c
.getColumnIndex(DataBaseHandler.KEY_NAME));
System.out.println("null:");
System.out.println("Move " + idname);
return true;
}
c.close();
stopManagingCursor(c);
} catch (Exception ex) {
}

SQLite same result after update

Strange behaviour of SQLite update in ContentProvider.
Update method:
#Override
public int update(Uri uri, ContentValues updateValues, String whereClause, String[] whereValues) {
SQLiteDatabase db = TasksContentProvider.dbHelper.getWritableDatabase();
int updatedRowsCount;
String finalWhere;
db.beginTransaction();
// Perform the update based on the incoming URI's pattern
try {
switch (uriMatcher.match(uri)) {
case MATCHER_TASKS:
updatedRowsCount = db.update(TasksTable.TABLE_NAME, updateValues, whereClause, whereValues);
break;
case MATCHER_TASK:
String id = uri.getPathSegments().get(TasksTable.TASK_ID_PATH_POSITION);
finalWhere = TasksTable._ID + " = " + id;
// if we were passed a 'where' arg, add that to our 'finalWhere'
if (whereClause != null) {
finalWhere = finalWhere + " AND " + whereClause;
}
updatedRowsCount = db.update(TasksTable.TABLE_NAME, updateValues, finalWhere, whereValues);
break;
default:
// Incoming URI pattern is invalid: halt & catch fire.
throw new IllegalArgumentException("Unknown URI " + uri);
}
} finally {
db.endTransaction();
}
if (updatedRowsCount > 0) {
DVSApplication.getContext().getContentResolver().notifyChange(uri, null);
}
return updatedRowsCount;
}
Query method:
#Override
public Cursor query(Uri uri, String[] selectedColumns, String whereClause, String[] whereValues, String sortOrder) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
// Choose the projection and adjust the "where" clause based on URI pattern-matching.
switch (uriMatcher.match(uri)) {
case MATCHER_TASKS:
qb.setTables(TasksTable.TABLE_NAME);
qb.setProjectionMap(tasksProjection);
break;
// asking for a single comic - use the rage comics projection, but add a where clause to only return the one
// comic
case MATCHER_TASK:
qb.setTables(TasksTable.TABLE_NAME);
qb.setProjectionMap(tasksProjection);
// Find the comic ID itself in the incoming URI
String taskId = uri.getPathSegments().get(TasksTable.TASK_ID_PATH_POSITION);
qb.appendWhere(TasksTable._ID + "=" + taskId);
break;
case MATCHER_TASK_COMMENTS:
qb.setTables(TaskCommentsTable.TABLE_NAME);
qb.setProjectionMap(taskCommentsProjection);
break;
case MATCHER_TASK_COMMENT:
qb.setTables(TaskCommentsTable.TABLE_NAME);
qb.setProjectionMap(taskCommentsProjection);
String commentId = uri.getPathSegments().get(TaskCommentsTable.TASK_COMMENT_ID_PATH_POSITION);
qb.appendWhere(TaskCommentsTable._ID + "=" + commentId);
break;
default:
// If the URI doesn't match any of the known patterns, throw an exception.
throw new IllegalArgumentException("Unknown URI " + uri);
}
SQLiteDatabase db = TasksContentProvider.dbHelper.getReadableDatabase();
// the two nulls here are 'grouping' and 'filtering by group'
Cursor cursor = qb.query(db, selectedColumns, whereClause, whereValues, null, null, sortOrder);
// Tell the Cursor about the URI to watch, so it knows when its source data changes
cursor.setNotificationUri(DVSApplication.getContext().getContentResolver(), uri);
return cursor;
}
Trying to update and row.
int affectedRowsCount = provider.update(Uri.parse(TasksTable.CONTENT_URI.toString() + "/"+ taskId), task.getContentValues(), null, null);
affectedRowsCount is eqaul to 1
Check if row is updated
Cursor cs = provider.query(TasksTable.CONTENT_URI, new String[] {TasksTable.TASK_STATE_VALUE}, TasksTable._ID +" = ?", new String[] {String.valueOf(taskId)}, null);
if(cs.moveToFirst()) {
String state = cs.getString(cs.getColumnIndex(TasksTable.TASK_STATE_VALUE));
}
state is the same as before update. Though update went succesful because affectedRowsCount is equal to 1 but selecting by the same id the same row seems that row wasn't updated at all.
In your update method you are using a transaction, but you never set the result as successful, so everytime you reach db.endTransaction() a rollback is performed. That's why your update isn't stored.
The changes will be rolled back if any transaction is ended without
being marked as clean (by calling setTransactionSuccessful). Otherwise
they will be committed.
You need to use
db.setTransactionSuccessful();
when your update is finished without errors. In your code, it should be after both your db.update.

Android SQLite Query: Trouble with WHERE clause

Please let me know why my where clause isn't working. I tried using the query instead of rawquery but no luck.
try {
String categoryex = "NAME";
DBHelper dbHelper = new DBHelper(this.getApplicationContext());
MyData = dbHelper.getWritableDatabase();
Cursor c = MyData.rawQuery("SELECT * FROM " + tableName + where Category = '+categoryex'" , null);
if (c != null ) {
if (c.moveToFirst()) {
do {
String firstName = c.getString(c.getColumnIndex("Category"));
String age = c.getString(c.getColumnIndex("Text_Data"));
results.add( firstName + " Directions: " + age);
}while (c.moveToNext());
}
}
} catch (SQLiteException se ) {
Log.e(getClass().getSimpleName(), "Could not create or Open the database");
} finally {
if (MyData != null)
MyData.execSQL("DELETE FROM " + tableName);
MyData.close();
}
try... (you left out a double-quote before where.
Cursor c = MyData.rawQuery("SELECT * FROM " + tableName + " where Category = '" +categoryex + "'" , null);
I think you should use rawQuery in this form:
rawQuery("SELECT * FROM ? where Category = ?", new String[] {tableName, categoryex});
I think it's more secure this way.
Your quotes are buggered:
Cursor c = MyData.rawQuery("SELECT * FROM " + tableName + " where Category = '" + categoryex + "'" , null);
You also should read up on SQL injection attacks.
it will be more easy if you use this technique instead of rawQuery,its easy way change your table name, columns and where conditions accordingly.
public ArrayList<Invitees> getGroupMembers(String group_name) {
ArrayList<Invitees> contacts = new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase();
String[] projection = {COLUMN_CONTACT, COLUMN_PHONE_NUMBER};
String selection = COLUMN_GROUP_NAME + "=?";
String[] selectionArgs = {group_name};
Cursor cursor = db.query(GROUPS_TABLE_NAME, projection, selection, selectionArgs, null, null, null);
if (cursor.moveToFirst()) {
do {
Invitees invitees = new Invitees();
invitees.setUserName(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_CONTACT)));
invitees.setInviteePhone(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_PHONE_NUMBER)));
contacts.add(invitees);
} while (cursor.moveToNext());
}
return contacts;
}

Categories

Resources