How to use WHERE IN clause in Android Sqlite? - android
I am trying to execute an single update query where i have to update a single field for many persons.
Now the below query works :-
UPDATE PERSON SET ISSELECTED=1 WHERE ID IN (132,142,115,141,41,133,40,56,139,134,135,65,143,9,64,39,120,104,122,35,19,98,124,127,130,136,119,123,55,102,5,128,140,95,138,131,96,93,129,103,94,89,126,21,29,125,3,101,92,113,4,88,111,63,60,38,114,90,31,118,99,121,117,100,112,97,25,116,10,32,27,30,14,26,12,61,57,20,107,110,91,109,108,106,105,16,62,33,59,18,58,36,11,15,37,28,24,6,7,8,34,13)
But it does not return the number of updated rows when used with execSql or rawQuery
I am trying to form this query using the update method which returns the no. of rows affected
int rowsUpdatedSelected = db.update("PERSON", values, "ID" + " = ?", new String[] {id.toString()});
// where id is a StringBuilder object containing the ids like above
But this is not working.
You can write a method to make IN query string and use that as you selectionArgs. Like below
selectionArgs = idArray; // Where id array will be String[] and will contain all of your ids
selection = "ID" + makeInQueryString(idArray.length);
Where makeInQueryString() is
/**
* Creates where string which can be used for IN query. It creates string
* containing "?" separated by ",". This method can be used as below <br>
* ColumnName + makeInQueryString(size) <br>
* This will create IN query for provided column name.
*
* #param size
* size of the items
* #return IN query string of the form (?,?,?,?)
*/
public static String makeInQueryString(int size) {
StringBuilder sb = new StringBuilder();
if (size > 0) {
sb.append(" IN ( ");
String placeHolder = "";
for (int i = 0; i < size; i++) {
sb.append(placeHolder);
sb.append("?");
placeHolder = ",";
}
sb.append(" )");
}
return sb.toString();
}
Try this code.
Put single quote on your in you IN data
UPDATE PERSON SET ISSELECTED=1 WHERE ID IN ('132','142','115','14','1');
I didn't try this.. just give a try.. and let me know wethr its working or not..
int rowsUpdatedSelected = db.update("PERSON", values, "ID IN (?)", new String[] {id.toString()});
You can try using sqlite3_changes() for this:
This function returns the number of database rows that were changed or
inserted or deleted by the most recently completed SQL statement on
the database connection specified by the first parameter. Only changes
that are directly specified by the INSERT, UPDATE, or DELETE statement
are counted.
So after your update statement, add this code:
Cursor cursor = null;
try
{
cursor = db.rawQuery("SELECT changes() AS updated_row_count", null);
if(cursor != null && cursor.getCount() > 0 && cursor.moveToFirst())
{
final long count = cursor.getLong(0);
Log.d("LOG", "no. of updated rows : " + count);
}
} catch(SQLException e)
{
e.printStackTrace();
} finally
{
if(cursor != null)
{
cursor.close();
}
}
Hope this helps.
Related
Sqlite how to improve performance?
I have to make more than 300 selects from my database. Each of those queries has to be called inside of a for each loop, here's an example: for(int id : myids){ Cursor cursor = MyDatabaseHelper.runMyQuery(id); while(cursor.moveToNext()){ //my stuff... } } MyDatabaseHelper is an instance of a database helper class, the function is like this public Cursor runMyQuery(int id){ SQLiteDatabase db = this.getWritableDatabase(); Cursor ret = db.rawQuery("select Name, Surname, Age from PTable where Id = " + id, null); return ret; } I've been told that the constant "open and close" of the db because of multiple queries it the cause of my performance issues and I should, instead, make a single query (using union etc). Changing my code to a single query would mean changing the entire database, and I was hoping not to do that. Is there anything I can do to improve the performance and keep the multiple selects at the same time? Thanks
I think what you are looking for is the in clause. Convert your myids into a string. Something like String inClause = "(1,2,3)" and you can use it as "select Name, Surname, Age from PTable where Id in " + inClause You can read more of the in operator here
You can return a single Cursor containing all the rows. First change your runMyQuery() method to this: public Cursor runAll(String list){ SQLiteDatabase db = this.getWritableDatabase(); String sql = "select Name, Surname, Age from PTable where " + list + " like '%,' || id || ',%'" Cursor ret = db.rawQuery(sql, null); return ret; } So you pass to the method runAll() a String which is the the comma separated list of all the ids that you have in myids and with th eoperator LIKE you compare it to each id of the table. You create this list and get the results in a Cursor object like this: StringBuilder sb = new StringBuilder(","); for(int id : myids){ sb.append(String.valueOf(id)).append(","); } String list = sb.length() > 1 ? sb.toString() : ""; if (list.length() > 0) { Cursor c = runAll(list); while(c.moveToNext()){ //your stuff... } }
Set all returned data to textview from sqlite
I want to set the random data from my table to a single textview.I am able to fetch random data from sqlite but I can not set it to my textview.Probably I should not use setText to put it there. "Generate" function should bring each time random data from that table. - main class - I am having my problem down here (Part of the above class) private void generatecompliment() { Cursor cursor = mydb.generatecompliments(); cursor.moveToFirst(); String[] compliments1 = new String[cursor.getCount()]; //cursor.moveToNext(); shwtxt.setText(cursor.getString(1)); }} - databasehelper class- public Cursor generatecompliments () { SQLiteDatabase sqLiteDatabase2 = getReadableDatabase(); String sql ="SELECT * FROM " + TABLE_NAME2 + "ORDER BY RANDOM() LIMIT 1"; return sqLiteDatabase2.rawQuery(sql, null); } } Note:I have a third class which uses another table but I did not put it here since its working fine. Thanks for help.
You have two options I believe that you would want something like :- private void generatecompliment() { boolean done_first_column = false; StringBuilder sb = new StringBuilder(); Cursor cursor = mydb.generatecompliments(); if (cursor.moveToFirst()) { for (String column_name; cursor.getColumnNames) { if (done_first_column) { sb.append(" "); //<<<<<<<<<< separator between column data } sb.append(cursor.getString(csr.getColumnIndex(column_name)); done_first_column = true; } } cursor.close(); shwtxt.setText(sb.toString()); } or alternatively private void generatecompliment() { StringBuilder sb = new StringBuilder(); Cursor cursor = mydb.generatecompliments(); if (cursor.moveToFirst()) { for (int i =0; i < cursor.getColumnCount(); i++) { if (i > 0) { sb.append(" "); //<<<<<<<<<< separator between column data } sb.append(cursor.getString(i); } } cursor.close(); shwtxt.setText(sb.toString()); } The difference being that the first gets a String array of the column names using the Cursor getColumnNames method, whilst the second retrieves the number of columns retrieved from the Cursor getColumnCount method. This assumes that by saying all returned data that you want data from all columns concatenated. This also assumes that you want a space separating the data from each column. There is also the assumption that shwtxt has been appropriately instantiated. The above code is in-principle code, it has not been tested or run so it may caontain some small errors.
Cursor not working in Android sqlite
My android app has 2 tables Projects and Tasks. Each Project can have multiple Tasks. Like below Now I want to sum up all proportion values of the single task table I did it.. but the issue is its adding proportion values from all task tables ! The cursor I coded is as follows public int sumproportion(long projectId){ int value = 0; int p = 0; Cursor cu = mDatabase.rawQuery("SELECT * FROM " + DBHelper.TABLE_TASKS, null); ArrayList temp = new ArrayList(); if (cur != null) { if (cur.moveToFirst()) { do { temp.add(cur.getString(cur.getColumnIndex("proportion"))); // "Title" is the field name(column) of the Table } while (cur.moveToNext()); } } Object ia[] = temp.toArray(); for(int i=0; i<ia.length; i++) { p = Integer.parseInt((String) ia[i]); value = value + p; } System.out.println("Value is: " + value); return value; } When I added cursor as below Cursor cur = mDatabase.query(DBHelper.TABLE_TASKS, mAllColumns, DBHelper.COLUMN_TASK_PROJECT_ID + " ="+String.valueOf(projectId), null, null, null, null); It doesn't add anything. Can any one help fix it please?
First of all, you can just use query like this SELECT SUM(proportion) from TABLE_TASK. proportion should have numeric type. Secondly, verify that your Cursor return any rows. Probably you pass wrong projectId if there no rows.
Dynamic SQLite queries
I'm trying to implement dynamic queries in my Android app, to let the users search according to some criteria. In this case I'm trying to search simply by an integer value. Here's my attempt: ... public String[][] listarNegocio(int idProyecto, int minimo, int maximo) { String[][] arrayDatos = null; String[] parametros = {String.valueOf(idProyecto)}; Cursor cursor = null; cursor = querySQL("SELECT *" + " FROM negocio" + " WHERE ? in (0, id_proyecto)", parametros); if(cursor.getCount() > 0) { int i = minimo - 1; arrayDatos = new String[maximo - minimo + 1][20]; while(cursor.moveToNext() && i < maximo) { // Here I fill the array with data i = i + 1; } } cursor.close(); CloseDB(); return(arrayDatos); } public Cursor querySQL(String sql, String[] selectionArgs) { Cursor oRet = null; // Opens the database object in "write" mode. db = oDB.getReadableDatabase(); oRet = db.rawQuery(sql, selectionArgs); return(oRet); } ... I tested this query using SQLFiddle, and it should return only the rows where the column id_proyecto equals the parameter idProyecto, or every row if idProyecto equals 0. But it doesn't return anything. If I remove the WHERE clause and replace "parametros" with "null", it works fine. Additionally, I need to search by text values, using LIKE. For example, WHERE col_name LIKE strName + '%' OR strName = ''. How should I format my parameters and the query to make it work?
You should do one query for each case. For an id that exists, do SELECT * FROM negocio WHERE id_proyecto = ?. For an id that doesn't exist (I'm assuming 0 isn't a real id), just query everything with SELECT * FROM negocio. Code should be something like this: if(parametros[0] != 0){ cursor = querySQL("SELECT *" + " FROM negocio" + " WHERE id_proyecto = ?", parametros); } else { cursor = querySQL("SELECT *" + " FROM negocio", null); } Regarding your second question, it depends on what you're looking for, you could use LIKE '%param%' or CONTAINS for occurrences in between text, LIKE param for partial matches or just = param if you're looking an exact match.
Query a Sqlite Database Using an Array Android
I have researched a handful of other forums with a similar topic and I have yet to find an answer to this frustrating issue. I am trying to use an array to check if a column in my database has one of the multiple values in the array. My cursor is as follows: public Cursor notificationQuery(String geoIds) { Log.e("STRINGS", geoIds); return mDb.query(Constants.TABLE_POI_NAME, new String[]{Constants.TABLE_COLUMN_ID, Constants.TABLE_COLUMN_POI_NAME, Constants.TABLE_COLUMN_LATITUDE, Constants.TABLE_COLUMN_LONGITUDE, Constants.TABLE_COLUMN_GEO_ID}, Constants.TABLE_COLUMN_GEO_ID + " IN (?)", new String[]{geoIds}, null, null, null, null); } geoIds is currently an array of two values which has been converted into a string. The logged value of that string is below: 21007b0f-6b20-4eff-9a76-b412db8daa2e,26c695d6-6cb4-4c74-9933-281813a06fd9 Those are to separate Id values separated by a comma. When I test each one individually using "= ?" instead of "IN (?)" I get a proper match with the database and my cursor returns a value. However, when combined my cursor returns nothing when it should return two rows from the database. Please help me solve this issue! Thanks!
Consider a function String makePlaceholders(int len) which returns len question-marks separated with commas, then: public Cursor notificationQuery(String geoId1,String geoId2) { //assume we split this geoIds to 2 different values. you need to have 2 strings no 1 String[] ids = { geoId1, geoId2 }; // do whatever is needed first depends on your inputs String query = "SELECT * FROM "+ Constants.TABLE_POI_NAME + " WHERE "+ Constants.TABLE_COLUMN_GEO_ID +" IN (" + makePlaceholders(names.length) + ")"; return mDb.rawQuery(query, ids); // ids is the table above } Here is one implementation of makePlaceholders(int len): String makePlaceholders(int len) { if (len < 1) { // It will lead to an invalid query anyway .. throw new RuntimeException("No placeholders"); } else { StringBuilder sb = new StringBuilder(len * 2 - 1); sb.append("?"); for (int i = 1; i < len; i++) { sb.append(",?"); } return sb.toString(); } }
Or more simply, use the geoIds variable directly: public Cursor notificationQuery(String geoIds) { Log.e("STRINGS", geoIds); return mDb.query(Constants.TABLE_POI_NAME, new String[]{Constants.TABLE_COLUMN_ID, Constants.TABLE_COLUMN_POI_NAME, Constants.TABLE_COLUMN_LATITUDE, Constants.TABLE_COLUMN_LONGITUDE, Constants.TABLE_COLUMN_GEO_ID}, Constants.TABLE_COLUMN_GEO_ID + " IN (" + geoIds + ")", null, null, null, null, null); } This approach is less secure but will likely give you the result you expect.