Delete multiple rows in SQLITE (android) [closed] - android

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I want to delete all the rows from the table that match the ids in an array. I can do that by either of the below 2 methods (both are working). Can you please advice which one is better?
METHOD 1:
public void deleteRec(String[] ids) { //ids is an array
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_NAME, KEY_ID+" IN (" + new String(new char[ids.length-1]).replace("\0", "?,") + "?)", ids);
db.close();
}
METHOD 2:
public void deleteRec(String[] ids) { //ids is an array
String allid = TextUtils.join(", ", ids);
SQLiteDatabase db = this.getWritableDatabase();
db.execSQL(String.format("DELETE FROM "+TABLE_NAME+" WHERE "+KEY_ID+" IN (%s);", allid));
db.close();
}

Just forget about second method!
Your ids are all strings from numbers (otherwise SQL would fail), but for generic string data, passing data into SQL statements is never a good idea. Make you application vulnerable to SQL injection:
String.format("DELETE FROM t WHERE ID='%s', "1' AND 1=1 --")
// = "DELETE FROM t WHERE ID='1' AND 1=1 --'" => would delete all data!
and may fail your SQL statements:
String.format("DELETE FROM t WHERE v='%s', "It's me!")
// = "DELETE FROM t WHERE v='It's me!'" => syntactically incorrect (quote not escaped)!
EDIT: As ids are supplied as string array and probably KEY_ID refers a INT column, method 1 should be adapted to:
db.delete(TABLE_NAME, "CAST("+KEY_ID+" AS TEXT) IN (" + new String(new char[ids.length-1]).replace("\0", "?,") + "?)", ids);

Try this maybye it helps you :
String[] Ids = ......; //Array of Ids you wish to delete.
String whereClause = String.format(COL_NAME + " in (%s)", new Object[] { TextUtils.join(",", Collections.nCopies(Ids.length, "?")) });
db.delete(TABLE_NAME, whereClause, Ids);

read this documentation it says you should not use execSQL with INSERT, DELETE, UPDATE or SELECT because it can be a potential security risk. and still i believe regarding the performance the first one is better.

I used this:
String[] Ids = new String[]{"1", "2", "3"};
mContext.getContentResolver().delete(CONTENT_URI, ID + " IN (?, ?, ?)",Ids);
the multi ? work.

try this
public void deleteRec(String[] ids) { //ids is an array
SQLiteDatabase db = this.getWritableDatabase();
for (int i = 0; i < ids.length; i++) {
//Your code for delete
}
db.close();
}

Related

Deleting multiple rows using IN sql statement in whereClause [duplicate]

This question already has answers here:
IN clause and placeholders
(9 answers)
Closed 5 years ago.
I have a list that performs multiple selections then delete the items that are selected using this method.
public Integer deleteDesc(ArrayList<String> rows) {
String[] args = rows.toArray(new String[rows.size()]);
Log.i("AMS", "Args: " + args);
db = this.getWritableDatabase();
return db.delete("DropdownList", "Description IN (?)", args);
}
where the parameter ArrayList contains the items that were selected. I works when I only select one item but returns an error "bind or column index out of range".
I'm pretty sure it's the whereClause which cause it because I'm not sure how to correctly use the "?"
I used this statement TextUtils.join(",", Collections.nCopies(args.length, "?"));
working code:
public Integer deleteDesc(ArrayList<String> rows) {
String[] args = rows.toArray(new String[rows.size()]);
db = this.getWritableDatabase();
return db.delete("DropdownList", "Description IN (" + TextUtils.join(",", Collections.nCopies(args.length, "?"))
+ ")", args);
}
You can build the WHERE IN clause using ? placeholders for each value using a prepared statement:
SQLiteDatabase db = this.getWritableDatabase();
StringBuilder sql = new StringBuilder("DELETE FROM yourTable WHERE Description IN (?");
for (int i=1; i < args.length; i++) {
sql.append(",?");
}
sql.append(")");
SQLiteStatement stmt = db.compileStatement(sql.toString());
for (int i=0; i < args.length; ++i) {
stmt.bindString(i+1, args[i]);
}
stmt.execute();
Note that using a prepared statement here is probably highly recommended, since you are deleting data. Allowing a SQL injection in this method could have bad side effects.

How to update a row from a table in SQLite android by SQL command? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
My code that is not working update operation on Button click.
Button update_user= (Button) findViewById(R.id.update_user)
update_user.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
SignIn_Signup.sqLiteDatabase.execSQL("UPDATE mytable SET name = "+name1_updated.getText() +"
WHERE name=name1.getText()+ );
}
});
please help.
if you want to delete operation in Sqlite than , you have to use these query for it
db.execSQL("delete from "+YOUR_TABLE_NAME+" where YOUR_COLUMN_NAME='"+VALUE_BY_WHICH_YOU_WANT_TO_DELETE+"'");
And for the Update operation. Use these following query
SignIn_Signup.sqLiteDatabase.execSQL("UPDATE mytable SET name = '"+name1_updated.getText() +"' WHERE name='"name1.getText()"'";
Try to use rawQuery method
SignIn_Signup.sqLiteDatabase.rawQuery("UPDATE mytable SET name = '"+name1_updated.getText() + "'" + "WHERE name= "+"'"name1.getText() +"'" );
You are missing quotes in where clause
SignIn_Signup.sqLiteDatabase.execSQL("UPDATE mytable SET name = '"+name1_updated.getText() +"' WHERE name='"name1.getText()"'";
When it runs(eg):
UPDATE mytable SET name = 'psypher' WHERE name='neeraj';
Another way to do it:
ContentValues contentValues = new ContentValues();
contentValues.put("name", "psyhper");
getWritableDatabase().update("mytable", contentValues, "name" + "=?", new String[]{<put whatever name>});
I think the correct SQL statement is:
"UPDATE mytable SET name = " + name1_updated.getText() + " WHERE name = " + name1.getText());
For update operation make sure you have some appropriate constraint in your table, such as PRIMARY KEY. "insertWithOnConflict" method will do insert/update operation.
ContentValues contentValues = new ContentValues();
contentValues.put("name", "Dhruv");
mDatabase.insertWithOnConflict(DATABASE_TABLE_NAME, null, contentValues , SQLiteDatabase.CONFLICT_REPLACE);
At last my code is working
and that is:
Button update_user = (Button) findViewById(R.id.update_user);
update_user.setOnClickListener(new View.OnClickListener() {
#Override`
public void onClick(View view) {
SignIn_Signup.sqLiteDatabase.execSQL("UPDATE mytable SET name = '"+name1_updated.getText() +"' WHERE name='"+name1.getText()+"'");
}
});

Bulk Update Database

I've been looking on this site for a while but have not found the answer. I am trying to do a bulk update on data that I know is already in the table. I have one column that needs to be set when a certain condition comes back for the row ID. Here is the single method but I want to make this more efficient and do it as a bulk. Our database is not in a Provider so I just using a Helper class.
public void markUnavailable(int myId) {
SQLiteDatabase db = this.getWritableDatabase();
String sql = "UPDATE " + MYTABLE + " SET " + Col.IS_AVAILABLE + "= 0"+ " WHERE " + Col.MY_ID + "=" + myId;
db.execSQL(sql);
db.close();
}
I would like to pass in an array of myIds to do the bulk Update. I can't do a Insert or Replace statement because I don't have access to all the column data and don't want to pass this through due to too many codes changes.
public void markUnavailable(int[] myId) {
// ????
/// need some way to loop through and update in bulk
}
Try UPDATE tablename SET column=0 WHERE ID IN (...), where ... is a comma-delimited list of ID values.
I'm not an Android developer, but according to good database practices, you should:
public void markUnavailable(int[] myId) {
SQLiteDatabase db = this.getWritableDatabase();
db.beginTransaction();
SQLiteStatement upd=db.compileStatement("UPDATE "+MYTABLE+" SET "+Col.IS_AVAILABLE+"=0 WHERE "+Col.MY_ID+"=?";
for (int i = 0; i < myId.length; i++) {
upd.bindLong(1, myId[i]);
upd.execute();
}
db.endTransaction();
}
Android has SQLiteDatabase.update would be very usefull in this case, but String [] whereArgs would not deal well with your int[] myId.
The fastest way to do a bulk update would be to do it as a single transaction,by using begin and end transactions. Also if the size of the database is large it will be a good idea to make myID as the primary key of the table as it will significantly increase the speed of the speed in fetching the rows for update when the WHERE clause is used.[It is said that indexing can reduce the speed of update and insert but when the where clause is used,indexing has always increased my speed by huge margins.
public void markUnavailable(int[] myId) {
SQLiteDatabase db = this.getWritableDatabase();
db.beginTransaction();
SQLiteStatement upd=db.compileStatement("UPDATE "+MYTABLE+" SET "+Col.IS_AVAILABLE+"=0 WHERE "+Col.MY_ID+"=?");
for (int i = 0; i < myId.length; i++) {
upd.clearBindings();
upd.bindLong(1, myId[i]); // this matches the first "?"
upd.execute();
}
db.setTransactionSucessful();
db.endTransaction();
}

Sqlite UPDATE with parameterised IN (...) clause [duplicate]

This question already has answers here:
IN clause and placeholders
(9 answers)
Closed 10 years ago.
In my app I'm working with sqlite database - and I hit a strange issue.
I have a table that looks like this:
_id field1 field2 status
--- ------ ------ ------
1 value value ...
2 value value ...
...
At one place, I need to update some rows to set them to another status, so I'm trying
SQLiteDatabase db = getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put("status", STATUS_SENT);
Set<Integer> ids = datasource.getCompletedIds();
String idparam = TextUtils.join(",", ids);
int cnt = db.update(TABLE_ORDERS, cv, "_id in (?)", new String[] { idparam });
Log.d("db", "updated " + cnt + " rows");
db.close();
However nothing gets updated - and db.update returns 0. What am I missing?
I'm not happy recommending not using parameters, but it this case, it's actually easier than formatting all those ? markers (and with plain integers, just as safe):
db.update(TABLE_ORDERS, cv, "_id IN (" + idparam + ")", null);
Unfortunately you must list one insertion character ? for each id in your Set...
A popular fix is to write a quick utility to add the appropriate number of ?s based on the Set's size.

How to delete rows in SQLite with multiple where args?

I want to delete rows which satisfy any of multiple conditions.
For example, I pass a list of IDs, and I want to delete all rows with these IDs (IDs are unique).
This would be:
String[] ids = {"0", "1", "2", "3",...};
database.delete("rows" , "id=? OR id=? OR id=? OR id=? OR ..." , ids );
Is there any way to do it compact without multiple OR?
You may get it done through db.execSQL method and SQL's IN keyword. For example:
String args = TextUtils.join(", ", ids);
db.execSQL(String.format("DELETE FROM rows WHERE ids IN (%s);", args));
What you want to use is an IN clause, something like (with 4 IDs);
database.delete("rows", "id IN (?, ?, ?, ?)", ids );
Upon request, this is (one example of) how you can do it dynamically;
database.delete("rows",
"id IN (" + new String(new char[ids.length-1]).replace("\0", "?,") + "?)",
ids);
Android official documentation tells here that using execSQL is not the proper way to delete records.
I would like to suggest the following simple method. Using provided delete() api.
String[] idArray = new String[] {"1", "2", "3"};
String idsCSV = TextUtils.join(",", idArray);
SQLiteDatabase db = getWritableDatabase();
if (db != null) {
db.delete("table_name", "id IN (" + idsCSV + ")", null);
db.close();
}
You could use id IN (1, 2, 3, 4, ...) and directly print your array values inside the brackets:
database.delete("rows", String.format("id IN (%s)", StringUtils.join(ids, ",")));
As an alternative, I'd try to use some kind of flags column for such things (if there's something like being able to flag single entries for deletion; I don't know how your ID list is "built").
Here's an example which builds the "?, ?, ?, ..." placeholder string with StringBuilder. If there are many parameters, plain string concatenation would create lots of garbage, StringBuilder helps with that.
String[] ids = {"0", "1", "2", "3",...};
StringBuilder placeholders = new StringBuilder();
for (int i = 0; i < ids.length; i++) {
if (i != 0)
placeholders.append(", ");
placeholders.append("?");
}
String where = "id IN (" + placeholders.toString() + ")";
db.delete("rows", where, args);
I have done this using this :
Sqlite Statement Syntax :
db.delete(TABLE_NAME,"COLUMN IN (?)", new String[]{commaSaparatedString})
Example based on question :
String args = TextUtils.join(", ", ids);
db.delete("rows","id IN (?)", new String[]{args})
This work for my varchar ID.
public Integer deleteObjects(List<Object> objects){
if (objects.size()<1) return 0;
SQLiteDatabase db = getWritableDatabase();
StringBuilder strb= new StringBuilder();
for(int i = 0; i<objects.size();i++){
strb.append("'");
strb.append(objects.get(i).getId().toString());
strb.append("'");
// last element without comma
if (i<objects.size()-1) strb.append(",");
}
int rows = db.delete("table_name","id IN (" + strb + ")",null);
db.close();
return rows;
}
This build WHERE string with args directly. Equivalent to:
db.delete(TABLE_NAME,"id IN ('id0-maddog','id1-foo','id2-bar')",null);
👌

Categories

Resources