My Cursor is always -1 when i send a request to my database (sqlite) to load an image.
public Cursor getData(int id){
SQLiteDatabase db = this.getWritableDatabase();
String query = "SELECT * FROM " + TABLE_NAME + " WHERE ID = " + id;
Log.d(TAG, query);
Cursor data = db.rawQuery(query, null);
return data;
}
The result is an app crash and this log in the logcat:
FATAL EXCEPTION: main
Process: com.master.tobias.phono, PID: 10721
android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1
Edit: The query works fine with the DB Browser for SQLite.
Try cursor.moveToFirst() before accessing the cursor data
try this one
public Cursor getData(int id){
SQLiteDatabase db = this.getWritableDatabase();
String query = "SELECT * FROM " + TABLE_NAME + " WHERE ID = " + id;
Log.d(TAG, query);
Cursor cursor= db.rawQuery(query, null);
while(cursor.moveToFirst()){
//get your value over here
}
return data;
}
It's also beneficial to look at the Android documentation of methods as it provides more information as to what the method if expecting as parameters and will be returning. Firstly, the db.rawQuery
Runs the provided SQL and returns a Cursor over the result set.
SQLiteDatabase
As for the cursor, you need to check the existence of an object with the Cursor variable. This can be done via using the following method:
cursor.moveToFirst();
Move the cursor to the next row.
This method will return false if the cursor is already past the last entry in the result set.
Cursor
This method will return a boolean which you can use for further validation. If the boolean is false, the cursor doesn't contain any data/objects within. If it's true, you know you have existence of the data.
Therefore, you are missing this functionality where you'll need to move the object to the first row which will allow you to determine if the query was empty or not.
Related
I want to fetch phone number linked to particular email in the database. I am not able to find the query for it or how
public String getContactNumber(String email){
SQLiteDatabase db = this.getReadableDatabase();
String query = "SELECT " + COLUMN_USER_MOBILE_NUMBER + " FROM " + TABLE_USER + " WHERE " + email + " = " + COLUMN_USER_EMAIL;
Cursor cursor = db.rawQuery(query,null);
//What to put here to extract the data.
String contact = cursor.getString(get);
cursor.close();
return contact;
}
to extract the data. Completely a beginner
Try this ..
public List<String> getMyItemsD(String emailData) {
List<String> stringList = new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase();
String selectQuery = "SELECT COLUMN_USER_MOBILE_NUMBER FROM " + USER_TABLE_NAME + " WHERE email= " + emailData;
Cursor c = db.rawQuery(selectQuery, null);
if (c != null) {
c.moveToFirst();
while (c.isAfterLast() == false) {
String name = (c.getString(c.getColumnIndex("Item_Name")));
stringList.add(name);
c.moveToNext();
}
}
return stringList;
}
public String getContactNumber(String email){
String contact = "";
SQLiteDatabase db = this.getReadableDatabase();
String query = "SELECT " + COLUMN_USER_MOBILE_NUMBER + " FROM " + TABLE_USER + " WHERE " + email + " = " + COLUMN_USER_EMAIL;
Cursor cursor = db.rawQuery(query,null);
if(cursor.getCount()>0) {
cursor.moveToNext();
contact = cursor.getString(cursor.getColumnIndex(COLUMN_USER_MOBILE_NUMBER));
}
//What to put here to extract the data.
cursor.close();
return contact;
}
From this method you get phone number value of that email which you pass any other method easily.
I'd suggest the following :-
public String getContactNumber(String email){
String contact = "NO CONTACT FOUND"; //<<<<<<<<<< Default in case no row is found.
SQLiteDatabase db = this.getWritableDatabase(); //<<<<<<<<<< Generally getReadable gets a writable database
String[] columns_to_get = new String[]{COLUMN_USER_MOBILE_NUMBER};
String whereclause = COLUMN_USER_EMAIL + "=?";
String[] whereargs = new String[]{email};
Cursor cursor = db.query(TABLE_USER,columns_to_get,whereclause,whereargs,null,null,null);
//What to put here to extract the data.
if (cursor.moveToFirst()) {
contact = csr.getString(csr.getColumnIndex(COLUMN_USER_MOBILE_NUMBER));
}
cursor.close();
return contact;
}
The above does assumes that there will only be 1 row per email (which is most likely).
Explanations
A default value is set so that you can easily tell if an invalid/non-existent email is passed (you'd check the return value if need be (might be easier to simply have "" and check the length as a check)).
getReadableDatabase has been replaced with getWritableDatabase as unless there are issues with the database a writable database will be returned, as per :-
Create and/or open a database. This will be the same object returned
by getWritableDatabase() unless some problem, such as a full disk,
requires the database to be opened read-only. In that case, a
read-only database object will be returned. If the problem is fixed, a
future call to getWritableDatabase() may succeed, in which case the
read-only database object will be closed and the read/write object
will be returned in the future.
getReadableDatabase
Note no real problem either way;
The recommended query method has been used instead of the rawQuery method. This has distinct advantages, it builds the underlying SQL and also offers protection against SQL injection (just in case the email passed is input by a user).
this version of the method takes 7 parameters :-
The table name as a string
The columns to be extracted as an array of Strings (aka String array). null can be all columns.
The where clause less the WHERE keyword with ?'s to represent arguments (see next). null if no WHERE clause.
The arguments to be applied (replace ?'s 1 for 1) as a String array. null if none or no WHERE clause.
The GROUP BY clause, less the GROUP BY keywords. null if no GROUP BY clause.
The HAVING clause, less the HAVING keyword. null if no HAVING clause.
The ORDER BY clause, less the ORDER BY keywords. null if no ORDER BY clause.
SQLiteDatabase - query
- Note there are 4 query methods (see link for the subtle difference, I believe this is the most commonly used)
The data extraction is the new code. When a Cursor is returned it is at a position BEFORE THE FIRST ROW, so you need to move to a valid row. So the moveToFirst* method is suitable (note that if a move cannot be made by a move method that it will return false, hence how you can say if (cursor.moveToFirst())). The data is then extracted from the appropriate column use the **getString method, which takes an int as an argumnet for the column offset (0 in this case). However, using hard coded values can lead to issues so the getColumnIndex method is used to get the offset according to the column name (-1 is returned if the named column is not in the Cursor).
I am working with SQLite Database in android studio. My onCreate code:
#Override
public void onCreate(SQLiteDatabase db) {
String CREATE_MOODS_TABLE = "CREATE TABLE " + TABLE_NAME_MOODS + "("
+ COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + COLUMN_MOODS + " TEXT NOT NULL)";
db.execSQL(CREATE_MOODS_TABLE);
}
and my Queries:
#Override
public Uri insert(#NonNull Uri uri, ContentValues values) {
final SQLiteDatabase db = mMindsDbHelper.getWritableDatabase();
final SQLiteDatabase db2 = mMindsDbHelper.getReadableDatabase();
long id = db.insert(TABLE_NAME_MOODS, null, values);
String query = "SELECT * FROM "+ TABLE_NAME_MOODS;
Cursor returnCursor;
returnCursor = db2.rawQuery(query, null);
return null;
}
For debugging purpose I have added select query in this place.
when debugger hits these points, return id of db.insert returns some value(i.e. id of new inserted values). But select query doesn't return anything useful(it returns mCount as -1).
I have tries following query also but result is same.
returnCursor = db.query(TABLE_NAME_MOODS,
projection,
selection,
selectionArgs,
null,
null,
sortOrder);
Where is the problem.
But select query doesn't return anything useful(it returns mCount as -1)
rawQuery() compiles a query but does not execute it. Hence the count is -1 for a query that has not been executed yet. The same applies to query() since it's essentially just a wrapper for rawQuery(). A query that was executed and matched no records would have its count set to 0.
To actually execute at least one step of a query compiled with rawQuery(), you need to call one of the moveTo...() methods on the returned Cursor. For example, moveToFirst().
I'm having a lot of trouble with checking if a cursor contains any results.
I have a method that "removes" all rows from a given table which is here:
Chevron.class
public void deleteAllRecords(){
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_NAME,null,null);
}
I then call a method which adds the SUM of the first row of the database which is here:
public Cursor getRecalculate(){
SQLiteDatabase db = this.getWritableDatabase();
Cursor res = db.rawQuery("select SUM (" + SECOND_FIELD + ") FROM " + TABLE_NAME, null);
return res;
}
My major issue is that if I remove all records from the database, res.getCount() still equals 1 but contains no information but then the method only returns 1 row anyway. So I'm stuck with how to check if the cursor has actual table data or just empty table data.
I've tried stuff like
if(res.getString(0) == null){
.. Do code
}
but that doesn't work.
I get the error:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.ceri.twostep_onecheck/com.example.ceri.twostep_onecheck.ShowGraph}: android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1
If you want to know how many rows there are that match your query constraints, add COUNT(*) to the SELECT statement:
SELECT COUNT(*), SUM(whatever) FROM other_thing;
Then, move the Cursor to the first row via moveToFirst(), and examine the two values (getInt(0) for the count and getInt(1) for the sum).
Use getReadableDatabase() instead of getWritableDatabase().
Try this:
public Cursor getRecalculate() {
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery("select SUM (" + SECOND_FIELD + ") FROM " + TABLE_NAME, null);
return res;
}
Read cursor value:
// Move the cursor to the first row if cursor is not empty
if(res.moveToFirst())
{
do
{
// Do something with cursor
}while(res.moveToNext()); // Move cursor to next row until it pass last entry
}
// Close
res.close();
Hope this will help~
Try this
cursor.getCount();
This should return at least one if cursor reads something or it will return zero.
I keep getting the following error
android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1
I know I have data in the database because a similar query for all the data (rather than a single entry) pulls out a list successfully
Here is my code for the database helper
public class DatabaseHandler extends SQLiteOpenHelper {
...
public Service getMostRecentService() {
SQLiteDatabase db = this.getReadableDatabase();
String selectQuery = "SELECT * FROM " + TABLE_CONTACTS + " ORDER BY " + KEY_ID + " DESC LIMIT 1;";
Cursor cursor = db.rawQuery(selectQuery, null);
Service service = new Service();
if(cursor != null) {
service = new Service(cursor.getString(1), cursor.getString(2));
}
return service;
}
}
Any ideas why I keep getting the out of bounds exception?
You have not positioned your Cursor on a row. Initially, it is at position -1. Presumably, given your existing code, you should call moveToFirst() on the Cursor after the null check and before your getString() calls.
Sorry if this seems obvious. I'm trying to write a method to delete a row from a String showId. What would be the best way, and can Cursors only be used for Selects or also for Deletes and Updates?
These are the two methods I'm at so far:
public int deleteShowById1(String showId){
Cursor cursor = db.rawQuery("DELETE FROM tblShows WHERE showId = '" + showId+"'", null);
if (cursor.moveToFirst()) {
return 1;
} else
return -1;
}
public int deleteShowById2(String showId) {
String table_name = "tblShows";
String where = "showId='"+showId+"'";
return db.delete(table_name, where, null);
}
As we know from mysql query, it is same here in android.
String query = "DELETE FROM " +TABLE_NAME+ " WHERE " + COLUM_NAME+ " = " + "'"+VALUE +"'" ;
SQLiteDatabase db = this.getWritableDatabase();
db.execSQL(query);
db.close();
VALUE may or may not have single quotation depending on datatype.
I tend to use the second method (db.delete), as I think using rawQuery is frowned upon.
If you do a select, then loop through the cursor to do updates or deletes, that would make sense, but to pass a cursor to do the delete or update doesn't make sense to me, as the program won't know how to parse the cursor results to get the correct fields.