I'm Parsing a JSON WebService and creating a array with data to INSERT and DELETE entries in a database.
I found the solution bulkInsert to insert multiple rows using database transactions inside a content provider, however, I am trying to do the same procedure to delete multiple lines.
The INSERT solution:
#Override
public int bulkInsert(Uri uri, ContentValues[] allValues) {
SQLiteDatabase sqlDB = mCustomerDB.getWritableDatabase();
int numInserted = 0;
String table = MyDatabase.TABLE;
sqlDB.beginTransaction();
try {
for (ContentValues cv : allValues) {
//long newID = sqlDB.insertOrThrow(table, null, cv);
long newID = sqlDB.insertWithOnConflict(table, null, cv, SQLiteDatabase.CONFLICT_REPLACE);
if (newID <= 0) {
throw new SQLException("Error to add: " + uri);
}
}
sqlDB.setTransactionSuccessful();
getContext().getContentResolver().notifyChange(uri, null);
numInserted = allValues.length;
} finally {
sqlDB.endTransaction();
}
return numInserted;
}
Using this call:
mContext.getContentResolver().bulkInsert(ProviderMyDatabase.CONTENT_URI, valuesToInsertArray);
Is there any way to delete multiple rows (with this array ID's) of database using content provider.
UPDATE:
I found this solution, using the `IN clause:
List<String> list = new ArrayList<String>();
for (ContentValues cv : valuesToDelete) {
Object value = cv.get(DatabaseMyDatabase.KEY_ROW_ID);
list.add(value.toString());
}
String[] args = list.toArray(new String[list.size()]);
String selection = DatabaseMyDatabase.KEY_ROW_ID + " IN(" + new String(new char[args.length-1]).replace("\0", "?,") + "?)";
int total = mContext.getContentResolver().delete(ProviderMyDatabase.CONTENT_URI, selection, args);
LOGD(TAG, "Total = " + total);
The problem is that, if the JSON return more than 1000 rows to insert, occurs error, because the SQLITE_MAX_VARIABLE_NUMBER is set to 999. It can be changed but only at compile time.
ERROR: SQLiteException: too many SQL variables
Thanks in advance
I solved this issue with this code:
if (!valuesToDelete.isEmpty()) {
StringBuilder sb = new StringBuilder();
String value = null;
for (ContentValues cv : valuesToDelete) {
value = cv.getAsString(kei_id);
if (sb.length() > 0) {
sb.append(", ");
}
sb.append(value);
}
String args = sb.toString();
String selection = kei_id + " IN(" + args + ")";
int total = mContext.getContentResolver().delete(uri, selection, null);
LOGD(TAG, "Total = " + total);
} else {
LOGD(TAG, "No data to Delete");
}
Thanks
User ContentResolver object to delete multiple rows.
// get the ContentResolver from a context
// if not from any activity, then you can use application's context to get the ContentResolver
// 'where' is the condition e.g., "field1 = ?"
// whereArgs is the values in string e.g., new String[] { field1Value }
ContentResolver cr = getContentResolver();
cr.delete(ProviderMyDatabase.CONTENT_URI, where, whereArgs);
So any row with (field1 = field1Value) will be deleted.
If you want to delete all the rows then
cr.delete(ProviderMyDatabase.CONTENT_URI, "1 = 1", null);
Related
I'm trying to get the value or data from the array that doesn't exists in the database.
public Cursor checkExistence(){
Cursor c=null;
String[] values={"headache","cold"};
SQLiteDatabase db= getReadableDatabase();
String query="SELECT * FROM "+TABLE_SYMPTOMS+" WHERE "+COLUMN_SYMP+" IN ("+toArrayRep(values)+")";
c=db.rawQuery(query,null);
Log.i("From Cursor","Cursor Count : " + c.getCount());
if(c.getCount()>0){
String val= c.getString()
Log.i("From Cursor","No insertion");
}else{
Log.i("From Cursor","Insertion");
}
db.close();
return c;
}
public static String toArrayRep(String[] in) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < in.length; i++) {
if (i != 0) {
result.append(",");
}
result.append("'" + in[i] + "'");
}
return result.toString();
}
In the String values={"headache","cold"} ,headache exists but cold does not exist in the database. From the code above, the Cursor returns Count=1 which is count>0 hence i can't insert into table.I would like to know how i can independently check whether the individual data exists, and the one which doesn't exist will be inserted into table.So in this case, "Cold" would be able to be inserted into the table.
If you use a single query to check all values, then what you get is a list of existing values, and you still have to search in the original list for any differences.
It is simpler to check each value individually:
String[] values = { "headache", "cold" };
SQLiteDatabase db = getReadableDatabase();
db.beginTransaction();
try {
for (String value : values) {
long count = DatabaseUtils.queryNumEntries(db,
TABLE_SYMPTOMS, COLUMN_SYMP+" = ?", new String[] { value });
if (count == 0) {
ContentValues cv = new ContentValues();
cv.put(COLUMN_SYMP, value);
db.insert(TABLE_SYMPTOMS, null, cv);
}
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
You need check Cursor.moveToFirst()
True = Have records in cursor.
False = Dont have records.
Example my code:
return database.query( table.getNameTable(),
table.getColumns(),
table.getWhereSelectTableScript(),
null,
table.getGroupBySelectTableScript(),
table.getHavingSelectTableScript(),
table.getOrderBySelectTableScript(),
table.getLimitRecordsSelectTableScript());
See more here !
So I am trying to delete only one instance of values from my SQLite database using the where args of db.update and db.delete in my app but it seems to delete and update all the matching ones. I only want to update or delete one. How do I do it? I tried using cursors but my implementation seems wrong. Help?
public long updateData(String oldFood, String oldCalorie, String newFood, Float newCalorie, String newDate) {
SQLiteDatabase db = helper.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(helper.FOOD_COLUMN, newFood);
contentValues.put(helper.CALORIE_COLUMN, newCalorie);
contentValues.put(helper.DATE, newDate);
String[] columns = {helper.UID, helper.FOOD_COLUMN, helper.CALORIE_COLUMN, helper.DATE};
//long id = db.update(helper.TABLE_NAME, contentValues, helper.FOOD_COLUMN + " = ? AND " + helper.CALORIE_COLUMN + " = ?", new String[]{oldFood, oldCalorie});
Cursor cursor = db.query(helper.TABLE_NAME, columns, null, null, null, null, null);
Information current = new Information();
int uidIndex = cursor.getColumnIndex(helper.UID);
int cid = cursor.getInt(uidIndex);
int foodIndex = cursor.getColumnIndex(helper.FOOD_COLUMN);
int calorieIndex = cursor.getColumnIndex(helper.CALORIE_COLUMN);
float oldCalorieFloat = Float.parseFloat(oldCalorie);
if (oldFood == cursor.getString(foodIndex) && oldCalorieFloat == cursor.getFloat(calorieIndex)) {
long id = db.update(helper.TABLE_NAME, contentValues, helper.FOOD_COLUMN + " = ? AND " + helper.CALORIE_COLUMN + " = ?", new String[]{oldFood, oldCalorie});
db.close();
return id;
}
long id=0;
return id;
}
I have a List of contacts with check box.When the user checks the check box i have updated my table field selectedValue with value=1 .Now what i want is i wamna get all the contacts in comma seperated way where selectedValue=1.So for that i have written a query.But my result is not desired.
For eg
I have 4 contacts A,B,C,D in a list.Now if user selects A and C from the list and when i fire that query to get the contacs comma seperated,this is what i get
A,A,C,C
I dont know why 2 values of A and C are comming
Code
public StringBuilder getCheckedContact() {
database = getWritableDatabase();
StringBuilder values = new StringBuilder();
String query = "Select * From " + contactTable + " where " + selectedContact + "=1";
Cursor c = database.rawQuery(query, null);
while (c.moveToNext()) {
for (int i = 0; i < c.getCount(); i++) {
values.append(c.getString(c.getColumnIndexOrThrow(contactName)));
if (i != c.getCount() - 1) {
values.append(",");
}
}
}
c.close();
database.close();
return values;
}
Your while loop loops over the results once, then the for loop loops over the results second time. If you select 4 contacts, you'd get 4*4=16 results.
Why did you add the inner for loop?
This could be rewritten as follows:
public StringBuilder getCheckedContact() {
database = getWritableDatabase();
StringBuilder values = new StringBuilder();
String query = "Select * From " + contactTable + " where " + selectedContact + "=1";
Cursor c = database.rawQuery(query, null);
boolean firstItem = true;
while (c.moveToNext()) {
if(firstItem)
firstItem = false;
else
values.append(",");
values.append(c.getString(c.getColumnIndexOrThrow(contactName)));
}
c.close();
database.close();
return values;
}
I'm executing the following method with no success beacause of the selectArgs being incorrect (at least this is what I believe.
findAll:
public Collection<Object> findAllByCodigoSetorOrderByStatusWhereDataAgendamentoIsNull(Integer vendedor) {
Collection<Object> objects = null;
String selection = Object.FIELDS[20] + "=?" + " OR " + Object.FIELDS[20] + "=?" + " OR " + Object.FIELDS[20] + "=?" + " AND " + Object.FIELDS[6] + "=?";
String[] selectionArgs = new String[] { "''", "'null'", "NULL", String.valueOf(vendedor) };
Collection<ContentValues> results = findAllObjects(Object.TABLE_NAME, selection, selectionArgs, Object.FIELDS, null, null, Object.FIELDS[4]);
objects = new ArrayList<Object>();
for (ContentValues result : results) {
objects.add(new Object(result));
}
return objects;
}
findAllObjects:
protected Collection<ContentValues> findAllObjects(String table, String selection, String[] selectionArgs, String[] columns, String groupBy, String having, String orderBy) {
Cursor cursor = null;
ContentValues contentValue = null;
Collection<ContentValues> contentValues = null;
try {
db = openRead(this.helper);
if (db != null) {
cursor = db.query(table, columns, selection, selectionArgs, groupBy, having, orderBy);
contentValues = new ArrayList<ContentValues>();
for (int i = 0; i < cursor.getCount(); i++) {
cursor.moveToPosition(i);
contentValue = new ContentValues();
for (int c = 0; c < cursor.getColumnCount(); c++) {
contentValue.put(cursor.getColumnName(c), cursor.getString(c));
}
contentValues.add(contentValue);
cursor.moveToNext();
}
}
return contentValues;
} finally {
close(db);
}
}
How can I correctly select and compare a column to - null, 'null' and '' using the db.query?
Android's database API does not allow to pass NULL values as parameters; it allows only strings.
(This is a horrible design bug. Even worse, SQLiteStatement does allow all types for parameters, but works only for queries that return a single value.)
You have no choice but to change the query string to blah IS NULL.
Old question but i was still stuck on this for a few hours until i found this answer. For whatever reason this strange behaviour (or bug) still exists within the android sdk, if you want to query against null values simply do
SQLiteDatabase db = getReadableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("columnName", newValue);
String nullSelection = "columnName" + " IS NULL";
db.update("tableName", contentValues, nullSelection, null);
db.close();
In this example i am updating values, but it is a similar concept when just selecting values
As mentioned in other answers, for null "IS NULL" need to be used. Here is some convenience code for having both null and strings (I'm using delete in the example but the same can be done for other methods, e.g. query):
public void deleteSomething(String param1, String param2, String param3) {
ArrayList<String> queryParams = new ArrayList<>();
mDb.delete(TABLE_NAME,
COLUMN_A + getNullSafeComparison(param1, queryParams) + "AND " +
COLUMN_B + getNullSafeComparison(param2, queryParams) + "AND " +
COLUMN_C + getNullSafeComparison(param3, queryParams),
queryParams.toArray(new String[0]));
}
private String getNullSafeComparison(String param, List<String> queryParams) {
if (param == null) {
return " IS NULL ";
} else {
queryParams.add(param);
return " = ? ";
}
}
You can bind NULL values to SQLiteStatement:
SQLiteDatabase db = getWritableDatabase();
SQLiteStatement stmt = db.compileStatement("UPDATE table SET " +
"parameter=? WHERE id=?");
if (param == null)
stmt.bindNull(1);
else
stmt.bindString(1, param);
stmt.execute();
stmt.close();
db.close();
I'm running an update query that compiles. But when I test the results, there seem to be no changes. Everything looks good to me, but clearly something is wrong. Can anyone see what I am missing. Pretty new to SQLite, so apologies if it's something simple. Thanks!
public static Boolean updateHealth (int unitVal, int oldValue, int newValue) {
String unit = Integer.toString(unitVal);
String oldVal = Integer.toString(oldValue);
String newVal = Integer.toString(newValue);
System.err.printf("old val: %s, new val: %s\n", oldVal, newVal);
SQLiteDatabase db = myDBOpenHelper.getWritableDatabase();
String where = UNIT_COLUMN + " = " + unit + " AND " + HEALTH_COLUMN + " = " + oldVal;
Cursor cursor = db.query(UNITS_TABLE, new String[] {UNIT_COLUMN}, where, null, null, null, null);
if (cursor != null) {
/* the record doesn't exist, cancel the operation */
return false;
}
ContentValues updatedValues = new ContentValues();
updatedValues.put(HEALTH_COLUMN, newVal);
/* SQL query clauses */
String whereArgs[] = null;
db.update(UNITS_TABLE, updatedValues, where, whereArgs);
return true;
}
The cursor is not null when no row is retrieved. So you have to replace the line if (cursor != null) { by if(!cursor.moveToNext()) {
By the way, you don't need to query the database before updating. You can do the update, see how many rows have been affected and return true if the number of affected rows is > 0, false otherwise. The number of affected rows is returned by the method update.