How can I delete multiple rows by a list of IDs in Android SQLite database?
I have defined a general delete method in this manner:
protected void deleteWhere(String whereClause, String[] whereArgs) {
try {
databaseHelper.getWritableDatabase().delete(
getTableName(), whereClause, whereArgs);
} finally {
databaseHelper.close();
}
}
And now I'm trying to call it with a list of IDs:
public void deleteAll(Iterable<T> entities) {
Iterable<Long> ids = Iterables.transform(entities, getId);
String whereClause = getIdColumn() + " IN (?)";
String[] whereArgs = { TextUtils.join(",", ids) };
deleteWhere(whereClause, whereArgs);
}
If the ID list contains for example the values [1, 2, 42], then I assume the resulting SQL should be:
DELETE FROM tableName WHERE _id IN (1,2,42);
But this doesn't seem to work correctly. If the list contains only 1 ID, then it is correctly deleted. However, if I provide multiple values, than zero rows are affected. What am I doing wrong?
When you give a single string as whereArgs, a single string ends up in the SQL command, as if you had written this:
... WHERE _id IN ('1,2,42')
This would compare each _id value against the value '1,2,42', which of course does not work.
If you use three parameter markers and give three strings in the whereArgs array, you would end up with three strings, like this:
... WHERE _id in ('1','2','42')
This works only when the _id column has integer affinity, which is true for a column declared as INTEGER PRIMARY KEY, but not in the general case.
The Android database API does not allow query parameters to have any type but string.
When using integers, you should just insert them directly (as in ianhanniballake's answer):
String whereClause = getIdColumn() + " IN (" + TextUtils.join(",", ids) + ")";
You can't use whereArgs for IN statements due to the escaping done by whereArgs (unless you make a separate ? for each value) - instead, you have to embed the ids in your where statement:
String whereClause = getIdColumn() + " IN (" + TextUtils.join(",", ids) + ")";
deleteWhere(whereClause, null);
Each "?" will only bind to a single value. So if your id list has three values, your whereClause would need to be "_id IN (?,?,?)"
Related
I am using this method to get query for this string:
public void deletedata(){
p=srt.split(",");
DatabaseHandler dba=new DatabaseHandler(this);
for(String s:p) {
dba.removeSingleproduct(s);
}
Database method is :
public boolean removeSingleproduct(String name) {
SQLiteDatabase db = this.getWritableDatabase();
return db.delete(tablename, productinserted + "=" + name, null) > 0;
}
I want to delete only one row by calling database as product inserted can have two same value.
Please help guys.
Since you're deleting with a selectedValue String,
add a single quote before and after the name
return db.delete(tablename, productinserted + " = '" + name + "'", null) > 0;
Or you can simplify your code.
public int removeSingleproduct(String name) {
return getWritableDatabase().delete(tablename, productinserted + " = ?", new String[] { name });
}
Return int - the number of rows affected if a whereClause is passed in, 0 otherwise. To remove all rows and get a count pass "1" as the whereClause.
The following will use the name to locate all rows with the provided name but only delete the first according to it's rowid (unless WITHOUT ROWID has been specified [very likely not]).
public boolean removeSingleproduct(String name) {
boolean rv = false;
SQLiteDatabase db = this.getWritableDatabase();
Cursor csr = db.query(tablename,new String[]{"rowid AS dltid"},productinserted + "=?",new String[]{name},null,null,null);
if(csr.moveToFirst()) {
rv = db.delete(tablename,"rowid=?",new String[]{Long.toString(csr.getLong(csr.getColumnIndex("dltid")))}) > 0;
}
csr.close();
return rv;
}
If you wanted to ensure that a row was only deleted if multiple rows with the same productinserted name existed, then you could simply change
if(csr.moveToFirst()) { ........
to
if(csr.moveToFirst() && csr.getCount() > 1) { .......
Note! csr.moveToLast() could be used instead of csr.moveToFirst() it would probably then delete the newest addition rather than probably deleting the oldest addition.
If you think
but I haven't defined a column called rowid
then :-
Except for WITHOUT ROWID tables, all rows within SQLite tables have a
64-bit signed integer key that uniquely identifies the row within its
table. This integer is usually called the "rowid". The rowid value can
be accessed using one of the special case-independent names "rowid",
"oid", or "rowid" in place of a column name. If a table contains a
user defined column named "rowid", "oid" or "rowid", then that name
always refers the explicitly declared column and cannot be used to
retrieve the integer rowid value.
SQL As Understood By SQLite - ROWIDs and the INTEGER PRIMARY KEY
I have created a sqlite table for my android app, this table has 5 columns and multiple rows, the columns being: _id, column1, column2, column3, column4.
I want to delete a specific record, for instance the record stored in column3 corresponding to _id (in a different class are the getters and setters, for this I've named the class "TableHandler")
I guess that I'm a bit confused, following is what I was planning, but for column3 I'm not sure what should be the argument, I just want to delete whatever is in that column position corresponding to _id
public void deleteValueColumn3(TableHandler value){
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_NAME, KEY_ID + " = ? AND " + KEY_COLUMN3 + " = ?",
new String[] {String.valueOf(value.getID()), ?????????);
db.close();
}
The ???????? is that I'm stuck there, maybe the whole method needs to be rewritten, I would appreciate your input.
Thanks
If you want to delete the whole record, just use the _id of the record in delete method, because that is the primary key for your table and therefore is unique. If you'd rather keep the record, you con always use the SQLiteDatabase.update method, specifying null as the new value that will replace column3 value; check out that column3 declaration has no NOT NULL tag, otherwise that could easily throw exception at you.
SQLite does not allow you to delete columns for a specific row.
You can only delete ROWS of data (delete the row that has the column _ID = 1).
Here's a quick tutorial on SQL.
How about updating that column with a null value, rather than using delete()?
ContentValues cv = new ContentValues();
cv.putNull(KEY_COLUMN3);
db.getWritableDatabase().update(
TABLE_NAME,
cv,
KEY_ID + "=?",
new String[]{String.valueOf(keyIdValue)});
I am facing a problem in updating a table with multiple columns in where clause of the db.update in sqlite.
Below is what I have tried but not accepting and showing syntax error.
db.getWritableDatabase().update(tablename, update((buy+dupbuy)), (column2+"=? and"+ column3+"=?"),(new String[] {getdate}+" and"+new String[] {stockname}));
In above query
First parameter is tablename to be updated.
second parameter is value to be updated which will point to another class update method where I wrote content values for updating the table
Major one third part is parameters I need to pass in where clause.
but giving syntax error
The method update(String, ContentValues, String, String[]) in the type SQLiteDatabase is not applicable for the arguments (String, ContentValues, String, String)
How can I declare multiple columns in where clause?
Try changing
db.getWritableDatabase().update(tablename, update((buy+dupbuy)), (column2+"=? and"+ column3+"=?"),(new String[] {getdate}+" and"+new String[] {stockname}));
to
db.getWritableDatabase().update(tablename, update((buy+dupbuy)), (column2+"=? and "+ column3+"=?"),(new String[] {getdate,stockname}));
Add a space after the "and" in the WHERE clause and you need to pass a String[] and not String in the whereArgs parameter. Currently you are passing a String
Change the stretch code:
db.getWritableDatabase().update(tablename, update((buy+dupbuy)), (column2+"=? and"+ column3+"=?"),(new String[] {getdate}+" and"+new String[] {stockname}));
To
db.getWritableDatabase().update( tablename, update(buy+dupbuy), column2 + " = ? and " + column3 + " = ?", new String[]{ getdate, stockname } );
public static final String KEY_HIGH
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL("CREATE TABLE " + DATABASE_TABLE + " (" +
KEY_HIGH + " INTERGE);"
);
}
public long createEntry(String high) {
ContentValues cv = new ContentValues();
cv.put(KEY_HIGH, high);
return ourDatabase.insert(DATABASE_TABLE, null, cv);
}
String[] columns = new String[]{KEY_HIGH,KEY_NAME};
Cursor c = ourDatabase.query(
DATABASE_TABLE,
columns, null, null, null, null, KEY_HIGH + " DESC");
I am trying to sort by the column KEY_HIGH, however, the result came out like this:
4
3
2
10
11
1
How do I sort them as numbers from highest to lowest?
thanks.
From the Android docs:
public Cursor query (String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
Added in API level 1
Query the given table, returning a Cursor over the result set.
Parameters
table The table name to compile the query against.
columns A list of which columns to return. Passing null will return all columns, which is discouraged to prevent reading data from storage that isn't going to be used.
selection A filter declaring which rows to return, formatted as an SQL WHERE clause (excluding the WHERE itself). Passing null will return all rows for the given table.
selectionArgs You may include ?s in selection, which will be replaced by the values from selectionArgs, in order that they appear in the selection. The values will be bound as Strings.
groupBy A filter declaring how to group rows, formatted as an SQL GROUP BY clause (excluding the GROUP BY itself). Passing null will cause the rows to not be grouped.
having A filter declare which row groups to include in the cursor, if row grouping is being used, formatted as an SQL HAVING clause (excluding the HAVING itself). Passing null will cause all row groups to be included, and is required when row grouping is not being used.
orderBy How to order the rows, formatted as an SQL ORDER BY clause (excluding the ORDER BY itself). Passing null will use the default sort order, which may be unordered.
Returns
A Cursor object, which is positioned before the first entry. Note that Cursors are not synchronized, see the documentation for more details.
See Also
Cursor
Note that the final is named orderBy. This is where you can specify which column (or columns) to sort on. Also note that you do not need to include the "ORDER BY" keywords that you would use in a SQL statement.
I was having the same problem.It has a very simple solution:
In your CREATE_TABLE statement do this: " INTEGER, "+KEY_HIGH+ //your remaining things.
no need for the comma after the last null
Cursor c = ourDatabase.query(
DATABASE_TABLE,
columns, null, null, null, null + " ORDER BY " + KEY_HIGH + " DESC");
Hi to All I am new to Android.
I am using SQLite DataBase in my Application
meanwhile I am Written Queries using +
Like delete from tablename where value = + value;
this is my query
String delete_query = "delete from " + tableName
+ " where title = '" + title + "'";
database.execSQL(delete_query);
I want to write this Query using placeholder ?.
so that i tried
database.delete(tableName, title + "?" , new String[] {title});
instead "?" i tried (?)/('?')/'?'
but it is giving me an error....
can any one tell me how to write appropriate query using ?.....
Thanks in Advance.
Mahaveer
Make sure you have put the equal sign:-
database.delete(tableName, title + "=?" , new String[] {title});
As far as possible, try to use the less raw queries you can. Two advantages:
Query parameters will be escaped by the system (protection against SQL injection)
The code will be more readable
See the delete function of SQLiteDatabase class
public int delete (String table, String whereClause, String[]
whereArgs)
Convenience method for deleting rows in the
database.
table the table to delete from
whereClause the optional WHERE clause
to apply when deleting. Passing null will delete all rows.
Returns the number of rows affected if a whereClause is passed in, 0
otherwise. To remove all rows and get a count pass "1" as the
whereClause.
In your case:
final String where = "title=?";
final String[] args = new String[] { title };
database.delete(tableName, where, args);