Why is such DELETE query not working? - android

This is my method to delete a row from the database where appointment_date is equal to a date that was passed in
public void deleteAllAppointments(String date) {
SQLiteDatabase db = this.getWritableDatabase();
String deleteAllQuery = "DELETE FROM " + TABLE_APPOINTMENTS + " WHERE appointment_date = '" + date + "'";
db.rawQuery(deleteAllQuery, null);
Log.d("Query: ", deleteAllQuery);
}
I then use it like this
//Database (DatabaseHandler is the one that contains all database methods)
final DatabaseHandler database = new DatabaseHandler(this);
//This happens when button is clicked, it is tested an executes with every chick,
//#param selectedDate is a string like "18/03/2014"
database.deleteAllAppointments(selectedDate);
It executes and query looks like this
DELETE FROM appointments WHERE appointment_date = '18/03/2014'
However row with appointment_date = '18/03/2014' is not deleted.
I'm sure database is set up correctly as I have working methods with it and all information is received from there in correct format.
NOTE: Adding "*" to "DELETE * FROM..." returns a fatal syntax error.

rawQuery() just compiles the SQL but does not run it. To actually run it, use either execSQL() or call one of the moveTo...() methods on the cursor returned by rawQuery().
For further info, see What is the correct way to do inserts/updates/deletes in Android SQLiteDatabase using a query string?

For tasks such as insert or delete there are really great "convenience methods" like the [delete method](http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#delete(java.lang.String, java.lang.String, java.lang.String[])) already built in to the database.
public int delete (String table, String whereClause, String[] whereArgs)
As to why your current approach would fail, it could be something as simple the format of the column you're trying to delete not matching (e.g. you have created the table as a date value and not a string).
In any case, using the built in delete method is easier because it will notify you when it fails by returning the number of rows affected by the delete. rawQuery just returns a cursor, which you would then have to get the result from to see if it worked.

Are you sure your data value is in European format of day/month/year ala your query value of 18/03/2014 and maybe its not US style of month/day/year: 03/18/2014.
Not trying to be US-centric but that was my first thought.
Otherwise, definitely look at SQLiteDatabase.delete:
http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#delete(java.lang.String, java.lang.String, java.lang.String[])

Related

Initialize SQLite Cursor before accessing data from it

I am trying to insert data into a SQLite DB once a notification is received via FCM. For debugging purpose I am also inserting a dummy data into my DB when SHow Token is clicked on the HomeScreen activity.
However am getting
"I am getting "Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it."
Link to my code: - GitHub
Can someone please go through my code and let me know where I am going wrong.
Note - I added below in HomeScreen.java,MyFirebaseMessagingService.java and NotificationDetails.java
private SQLiteDB dbHelper = new SQLiteDB(this);
since the suggested
private SQLiteDB dbHelper;
did not work for me
When I used above I kept on getting Nullpointer exception, so I figured since the SQLiteDB class constructor is accepting a context, so let me pass one, post which I did not get NullPointer Exception.
Now I did this without being fully aware of the concept on context which I have been trying to wrap my head around, but since am an extreme noob to android I am not able to grasp it just yet. I suspect it might have something to do with the context I am passing.
Can someone please help me here with detailed instructions on how to fix this issue, I have been through many other threads on this but was not able to fix hence after 5 hrs of going through multiple SO questions, I am posting this one.
Thanks in advance to everyone in the community for the help. :)
Edit
Upon suggestion by admins, I am including below snippet of my code.
Where I am calling the cursor
dbHelper.insertNotification("This is a notification");
//Check if the message contains data
Cursor rs = dbHelper.getAllNotifications();
rs.moveToFirst();
token_text.setText("Token: " +rs.getString((rs.getColumnIndex("NOTIFICATION_DETAILS"))));
Insert Notification Function in SQLiteDB.java
public boolean insertNotification(String notification){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(NOTIFICATION_DETAILS,notification);
db.insert(NOTIFICATION_TABLE_NAME,null,contentValues);
return true;
}
getAllNotifications function
public Cursor getAllNotifications() {
SQLiteDatabase db = this.getWritableDatabase();
Cursor res = db.rawQuery( "SELECT * FROM " + NOTIFICATION_TABLE_NAME, null );
return res;
}
Couldn't read row 0, col -1 from CursorWindow.
Is saying that you are attempting to get the column at offset -1 from row 0 (the first row). So you have provided an invalid offset (it cannot be an offset of -1, the offset must be 0 or greater and the maximum value will be 1 less than the number of columns in the Cursor).
The most likely cause, is that Cursor method getColumnIndex(the_column_name_as_a_string) will return -1 when the column passed to the method cannot be found in the Cursor. Noting that due to a bug column name is case sensitive.
As such your issue is that the Cursor does not contain a column name NOTIFICATION_DETAILS and as you have used * (all columns) then that column does not exist in the table.
By the looks of it you should be using the String variable NOTIFICATION_DETAILS so you probably need to use :-
token_text.setText("Token: " +rs.getString((rs.getColumnIndex(NOTIFICATION_DETAILS)))); //<<<<<<<<<< double quotation marks removed.
Additional
You should NEVER assume that moveToFirst (or any Cursor move???? method) actually does the move. You should ALWAYS check the returned value. It will be true if the move was successful otherwise it would be false.
Again note that the column name passed to the getColumnIndex method is case dependant.
As such you should use something like
:-
dbHelper.insertNotification("This is a notification");
//Check if the message contains data
Cursor rs = dbHelper.getAllNotifications();
if (rs.moveToFirst()) {
token_text.setText("Token: " +rs.getString((rs.getColumnIndex(NOTIFICATION_DETAILS))));
} else {
........ code here if anything need to be done if there are no rows extracted
}
Addition re comment :-
Cursor rs = dbHelper.getAllNotifications(); rs.moveToFirst(); do{ for
(int i = 0; i < rs.getColumnCount(); i++) {
notification_array.add(rs.getString((rs.getColumnIndex(NOTIFICATION_DETAILS))));
} }while (rs.moveToNext());
using the following is much simpler :-
Cursor rs = dbHelper.getAllNotifications();
while (rs.moveToNext()) {
notification_array.add(rs.getString((rs.getColumnIndex(NOTIFICATION_DETAILS))));
}

Update query not updating the column using SQLite on Android

In my app, when the activity is destroyed, I want to update a column value to 0. For that I have written the query, but it seems not to be working for me, because when ever I start the app I get the same old values.
Code
public void resetSelectOptions() {
database = DatabaseManager.getInstance().openDatabase();
String query = "Update " + TableName + " SET " + Selected_Option + "=0";
try {
database.rawQuery(query, null);
}
catch (SQLiteException e) {
}
DatabaseManager.getInstance().closeDatabase();
}
How can I fix this problem?
Use this method to updating the rows,database.update() and
rawQuery is used to select query.
rawQuery() only executes queries (SELECT).
For any other SQL command, use execSQL().
So, simply convert this
database.rawQuery(query, null);
to this
database.execSQL(query, null);
It is not correct that the rawQuery() method executes only SELECT queries, it doesn't, but it is unnecessary to use it for an update, because you don't have any result - what to be iterated with the result Cursor at the ends, so try to use the execSQL() method. For more information take a look at this SO question android.database.sqlite.SQLiteDatabase.rawQuery() is not updating a DATETIME column with a SQLite datetime() function

SQLite get row data using SELECT

Using SQLite Database, I have a table with 6 columns in each row as the rows are added. The first column is the name of the "person." I have it so when you click on the person in a listview, it brings up a screen with 5 edit texts. You fill them out and submit it and it adds it to another row in the database.
To retrieve that data later on, I am trying to use SELECT by the name to get it, but cannot figure out how this works.
public Cursor getChildRulesInformation(DatabaseOperations dop, String name) {
dop.getReadableDatabase().execSQL("SELECT * FROM "+CHILD_RULES_TABLE_NAME+" WHERE "+CHILD_NAME + "=\""+ name+"\"");
}
What do I do with that to retreive every column inside of that specific row. I am confused on the process to get it out.
Any lead in the write direction would be greatly appreciated. Thanks. If you need any more information please let me know.
Try this,
public Cursor getChildRulesInformation(DatabaseOperations dop, String name) {
return dop.getReadableDatabase().rawQuery("SELECT * FROM "+CHILD_RULES_TABLE_NAME+" WHERE "+CHILD_NAME+" = '"+ name+"' ", null);}
Do not use execSql for getting data, that is only for sending data to the database. Instead, use rawQuery if you want to use the String. So it would be:
public Cursor getChildRulesInformation(DatabaseOperations dop, String name) {
return dop.getReadableDatabase().rawQuery("SELECT * FROM "+CHILD_RULES_TABLE_NAME+" WHERE "+CHILD_NAME + "='"+ name+"'", null);
}
This will return you the cursor object that you are looking for.

Sort values in child views of custom listview android

I designing a custom ListView ,which has more child view
I have ideas about sorting the ListViewdata in "Asc" or "Desc" order ,that retrieves data directly from database , but in my case I used CustomSimpleCursorAdapter , I requires to sort data in TextView depending upon the values that is:
today
tomorrow
more than 2 days i.e; 354
CustomSimpleCursorAdapter .java
//Days remaining for BirthDay
String year=cursor.getString(cursor.getColumnIndex(BirthdayProvider.EVENT_YEAR));
String month=cursor.getString(cursor.getColumnIndex(BirthdayProvider.EVENT_MONTH));
String date=cursor.getString(cursor.getColumnIndex(BirthdayProvider.EVENT_DATE));
String remainingDays=BirthdayCalculation.getDaysRemainingForNextBirthDay(year, month, date);
Calendar today=Calendar.getInstance();
int CMonth=(today.get(Calendar.MONDAY)+1);
int CDate=(today.get(Calendar.DAY_OF_MONTH));
//checking whether the BD is on TODAY
if (remainingDays.equals("1") && (CDate==Integer.parseInt(date) && (CMonth)==Integer.parseInt(month))) {
viewHolder.txtDaysRemainigValue.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
viewHolder.txtDaysRemainigValue.setTypeface(fontRoboto_Regular);
viewHolder.txtDaysRemainigValue.setTextColor(Color.parseColor("#00CC33"));
remainingDays="today";
}
//checking whether the BD is on TOMORROW
else if (remainingDays.equals("1")) {
viewHolder.txtDaysRemainigValue.setTextSize(TypedValue.COMPLEX_UNIT_SP, 17);
viewHolder.txtDaysRemainigValue.setTextColor(Color.parseColor("#FF0099"));
remainingDays="tomorrow";
viewHolder.txtDaysRemainigValue.setTypeface(fontRoboto_Regular);
}
//checking how many days remaining BD
else{
remainingDays=BirthdayCalculation.getDaysRemainingForNextBirthDay(year, month, date);
viewHolder.txtDaysRemainigValue.setTextSize(TypedValue.COMPLEX_UNIT_SP, 27);
viewHolder.txtDaysRemainigValue.setTextColor(Color.parseColor("#990000"));
}
Here's Screen Shot link
When you query your database, you should use an "order by" clause. For example, this method takes the order by clause as the last argument. I don't know how you store your dates and times in your database, but if it's something SQLite can recognize and provide sorting on, then it should work. The following will query for all columns on a table named "table" with no where clause, no "group by" clause, no "having" clause, and order by the time column descending (use ASC for ascending if you want that instead):
database.query("table", null, null, null, null, null, "time DESC");
EDIT
If you can't store the exact data you want (in this case days remaining until an event), I can only see two options:
1). After getting the cursor, you iterate over the results and compose a new sorted list. You could make some kind of model object in java, read the values into it from the cursor, and sort them with a comparator function. At that point you probably would not use a CursorAdapter any more. It's quite easy to build your own ListAdapter - I recommend you watch The World of Listview
2). Since the query methods take strings, you can actually compose more complicated queries so that SQLite provides you the data you DO want (and still sort it for you as well). If your times are stored as longs, you could do something like this:
long currentTime = System.currentTimeMillis();
String timeAsString = Long.toString(currentTime);
String remainingTimeColumn = "(time_column - " + timeAsString + ") AS remaining_time";
// compose query
String table = "table";
String[] columns = new String[] {"column1", "column2", ..., "columnN", remainingTimeColumn};
String order = "remaining_time ASC";
// query
Cursor cursor = database.query(table, columns, null, null, null, null, order);
// later, get remaining time from cursor row
long remainingTime = cursor.getLong(cursor.getColumnIndex("remaining_time"));
In this case "time_column" is the name of the column that stores the event time. What this is doing is creating an additional column with the name "remaining_time", which is calculated from one of the actual column values. The results are then sorted by that synthesized column. The cursor you get back will contain this column and these values, you just need to have the proper column name to access them.
Since I don't know the details of your data format, I can't say this is exactly how your query should look, but the idea should be clear. You can work out the finer details from here...
If you get the data in database, you can use ASC or DESC and put ArrayList.
another way is you can use Collections.sort(). but you must data class implements comparable and overriding compare method.

Quering SqlLite database where clause Android

Hi I am developing an android app.I am trying to query from the database. I need to fetch everything from the table TASK where dbDate = AlarmDate and dbdTime = AlarmTime.
c = db.rawQuery("SELECT * FROM TASK WHERE dbDate = '"+AlarmDate+"' AND dbTime= '"+Alarmtime+"'", null);
The problem is ,the cursor c is null.
I am not sure where I am going wrong in the query. Please Help.
Thanks!
Android has binding method to avoid sql inject. You can use the second parameter to provide the variables of SQL.
Cursor cur = db.rawQuery("SELECT * FROM TASK WHERE dbDate = ? AND dbTime = ? ", new String[]{AlarmDate, AlarmDate});
Going by your comment 'I have used db = openOrCreateDatabase("Globus", 0, null); where Globus is the db name', you are not using SQLite properly with android.
What you should be doing is creating class which extends SQLiteOpenHelper, then make sure you override the onCreate and onUpgrade methods, these are the methods where you create tables and make changes, it has been said a hundred times on here so I will provide a link to a tutorial: http://www.codeproject.com/Articles/119293/Using-SQLite-Database-with-Android
When you do database operations, on the class call getWritableDatabase (http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html#getWritableDatabase())
I say call getWritableDatabase because that way you don't need to worry if you can write to it, a writable database is also readable. Just FYI. Ask away for more details.
This should be the process of reading (writing is the same, just use what method you want instead of query):
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.beginTransaction();//this should lock the tables you are reading
Cursor c = db.rawQuery("select 1 where 1=?", new String[]{"1"});
if(c.moveToFirst()){
do{
//Do what you want with the row
}while(c.moveToNext());
}
c.close();
db.setTransactionSuccessful();
db.endTransaction();
db.close();
Here is the source code of a database helper I wrote, maybe it will help, read through it, understand how it works. https://bitbucket.org/FabianCCook/dbhelper/src/af7a8eba8d1a3f139e4170bbef9f1a2d3fdf1b47/src/nz/smartlemon/DatabaseHelper/ApplicationDataDbHelper.java?at=master
And if you want to know the reason the open methods exist read through this code
(This class was made from the help of someone elses code)
https://bitbucket.org/FabianCCook/dbhelper/src/af7a8eba8d1a3f139e4170bbef9f1a2d3fdf1b47/src/nz/smartlemon/DatabaseHelper/SDCardSQLiteOpenHelper.java?at=master
SQLiteDatabase db = getReadableDatabase();
Cursor cur = db.rawQuery("SELECT * FROM TASK WHERE dbDate = '"+AlarmDate+"' AND dbTime = '"+AlarmTime+"'",new String [] {});
Make sure you have gotten a readable database for 'db' or it will return null everytime.
Also change the end of your raw query to new String [] {}
Hope this helps, this is what I use in my applications.

Categories

Resources