I keep getting android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1 exception when trying to get a single row from a Sqlite table using a ID value.
Why do you think this happens? What is wrong with my code?
public Product getProduct(DBOps dop, String productId) {
Product p = new Product();
String sqlQuery = "SELECT " + TableInfo.PID + " FROM "
+ TableInfo.TABLE_NAME +" WHERE pid="+"'"+productId+"'";
SQLiteDatabase SQ = dop.getReadableDatabase();
Cursor CR = SQ.rawQuery(sqlQuery, null);
try
{
if(CR.getCount() > 0)
{
while (!CR.isAfterLast()) {
p.PID = CR.getString(0);
p.NAME = CR.getString(1);
p.SIZE = CR.getString(2);
p.COLORS = CR.getString(3);
p.DESC = CR.getString(4);
p.PRICE= CR.getString(5);
p.OUTLETS = CR.getString(6);
p.FABRIC = CR.getString(7);
p.QUANTITY = CR.getString(8);
p.CATEGORY = CR.getString(9);
p.RATING = CR.getString(10);
CR.moveToNext();
}
}
else
{
CR.close();
}
}
catch(Exception ex)
{
Log.e("DBOps Error", "Look at DBOps Class's getProduct Method");
Log.e("DBOps Error", ex.toString());
}
return p;
}
android.database.CursorIndexOutOfBoundsException: Index -1 requested,
with a size of 1
Because you are currently selecting only one column from table which is TableInfo.PID but trying to retrieve more then one column from cursor.
So change select query by specify all columns in select query or use * FROM get all columns:
String sqlQuery = "SELECT * FROM "
+ TableInfo.TABLE_NAME +" WHERE pid="+"'"+productId+"'";
Use Like This
if(cursor.getCount()>0)
{
if(cursor.moveToFirst())
{ do
{
//your code
}
while(cursor.moveToNext());
cursor.close();
}
}
Hope it will helps u
You need to call cursor.moveToFirst() before using the cursor. This moves it to row 0. Make sure to check the return value- if it returns false then it could not move to row 0 for some reason (generally it means 0 rows returned).
Related
I wanna use a String d as a parameter to select data from a sqlite database ..
- ID ------ DATE --------- VALUE
- 1 --------11/04/2020 ----2000
- 2 --------11/04/2020 ----4000
- 3 --------11/04/2020 ----1000
- 4 --------12/04/2020 ----700
- 5 --------13/04/2020 ----300
My getEntry() method looks like this :
public String getEntry(String d) {
// This value of storedEntry is returned if there is no data
String storedEntry = "Nothing!";
//here we use d to fetch data from table
String queryString = "SELECT * FROM "+TABLE_NAME+" WHERE "+DATE+"="+ d;
SQLiteDatabase db = this.getReadableDatabase();
String table;
Cursor cursor = db.rawQuery(queryString, null);
if(cursor.moveToFirst()) {
do {
storedEntry = cursor.getString(2);
} while (cursor.moveToNext());
} else {
//Do nothing!
}
return storedEntry;
}
My onClick method looks like this :
showDataBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
DataBaseHelper helper = new DataBaseHelper(HistoryActivity.this);
String v = helper.getEntry(dateEditText.getText().toString());
valueTextView.setText(v);
}
});
But, it returns an error :
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.darq2.myapplication, PID: 25073
android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
at android.database.AbstractCursor.checkPosition(AbstractCursor.java:460)
at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136)
at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:50)
at com.example.darq2.myapplication.DataBaseHelper.getEntry(DataBaseHelper.java:61)
WHY ??
The easy but not safe way to do this is by enclosing the parameter d inside single quotes and then concatenate:
String queryString = "SELECT * FROM "+TABLE_NAME+" WHERE "+DATE+"='"+ d + "'";
but as I said this is not safe.
Use ? placeholders for parameters:
String queryString = "SELECT * FROM "+TABLE_NAME+" WHERE "+DATE+"=?";
and also change:
Cursor cursor = db.rawQuery(queryString, null);
to:
Cursor cursor = db.rawQuery(queryString, new String[] {d});
Also, you should change the format of your dates.
SQlite recognizes only the format YYYY-MM-DD as a valid date.
android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
You are getting CursorIndexOutOfBoundsException.
An exception indicating that a cursor is out of bounds.
You should rectify your SELECT statement.
Cursor c = db.rawQuery("SELECT * FROM " + TABLE_NAME +" WHERE DATE =?", new String[]{d});
if (c.moveToFirst()){
do {
// Your work
}
while(c.moveToNext());
}
c.close();
db.close();
so i recently learn to write a code in android using sqlite and i try to select data from sqlite but this error occur
ive tried some suggestion from the internet and read my book but i didnt solve my problem
public Penyakit getPenyakit1(String namaGejal){
SQLiteDatabase db = this.getReadableDatabase();
String query = "SELECT idPen FROM " + TABLE_CONTACTS + " WHERE " +
namapen + " =\"" + namaGejal + "\"";
Cursor cursor = db.rawQuery(query,null);
Penyakit penyakit = new Penyakit();
if(cursor.moveToFirst()){
cursor.moveToFirst();
penyakit.set_nomber(Integer.parseInt(cursor.getColumnName(0)));
penyakit.set_namaPen(cursor.getColumnName(1));
penyakit.set_idPenyakit(Integer.parseInt(cursor.getColumnName(2)));
penyakit.set_namGej(cursor.getColumnName(3));
penyakit.set_idGejala(Integer.parseInt(cursor.getColumnName(4)));
cursor.close();
} else {
penyakit=null;
}
return penyakit;
}
this is logcat
Process: com.example.lordbramasta.pakar, PID: 18914
java.lang.NumberFormatException: For input string: "idPen"
at java.lang.Integer.parseInt(Integer.java:615)
at java.lang.Integer.parseInt(Integer.java:650)
at com.example.lordbramasta.pakar.DBAdapter.getPenyakit1(DBAdapter.java:79)
i expected the value of idPen get selected , thank you
Your problem is this line:
penyakit.set_nomber(Integer.parseInt(cursor.getColumnName(0)));
cursor.getColumnName(0) returns idPen as this is the name of the only column returned by your query:
SELECT idPen FROM ....
and your code is trying to cast the string "idPen" to an integer.
So getColumnName() returns the name of the column at a specified index and not the value of the column.
You should do
penyakit.set_nomber(Integer.parseInt(cursor.getString(0)));
or if the data type of the column idPen is INTEGER then:
penyakit.set_nomber(cursor.getInt(0));
Also don't try to get any other columns because your query returns only 1.
Note: remove that cursor.moveToFirst(); inside the if block because it is already executed.
Probably you need to use a ' instead of ". So, change the query to the following:
String query = "SELECT idPen FROM " + TABLE_CONTACTS + " WHERE " +
namapen + " =\'" + namaGejal + "\'";
I'm suggesting you to use SQLiteDatabase.query() instead rawQuery like this:
// Define a projection that specifies which columns from the database
// you will actually use after this query.
String[] projection = {
"idPen"
};
// Filter results WHERE "namapen" = 'namaGejal'
String selection = "namapen" + " = ?";
String[] selectionArgs = { namaGejal };
// How you want the results sorted in the resulting Cursor
String sortOrder = null; // null for default order
Cursor cursor = db.query(
TABLE_CONTACTS, // The table to query
projection, // The array of columns to return (pass null to get all)
selection, // The columns for the WHERE clause
selectionArgs, // The values for the WHERE clause
null, // don't group the rows
null, // don't filter by row groups
sortOrder // The sort order
);
// do something with the cursor
Please take a look Read information from a database
If you want to get all columns data from your TABLE_CONTACTS use SELECT * FROM
I have an SQLite Database in my android application with the following structure:
public void onCreate(SQLiteDatabase db) {
String CREATE_LISTS_TABLE = "CREATE TABLE " + TABLE_LISTS +
"("+
_ID + " INTEGER PRIMARY KEY , " +
NOTE + " TEXT" +
")";
db.execSQL(CREATE_LISTS_TABLE);
}
And this works, in that I can insert data into it without a problem. However I need to store the notes inside an array. I currently have the following query:
public List<String> getAllNotes() {
List<String> notes = new ArrayList<>();
String GET_ALL_NOTES = "SELECT * FROM " + TABLE_LISTS;
SQLiteDatabase db = getReadableDatabase();
if(db!=null)
{
Cursor cursor = db.rawQuery(GET_ALL_NOTES, null);
cursor.moveToFirst();
while(!cursor.isAfterLast())
{
notes.add(String.valueOf(cursor.getInt(cursor.getColumnIndex("notes"))));
cursor.moveToNext();
}
cursor.close();
}
db.close();
return notes;
}
However, this gives the following error:
java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
I was wondering how to fix this, I have read the android developer stuff but I can't seem to get anything to work.
Thanks in advance
Check the value of "NOTE", and use it in:
notes.add(String.valueOf(cursor.getInt(cursor.getColumnIndex(NOTE))));
I think a best way to make the call should be something like this:
// Check the cursor
if(cursor != null) {
if (cursor.moveToFirst()) {
// Variables to be used
String note;
// Col position
int colNote = cursor.getColumnIndex(NOTE);
do {
// Get the information
note = cursor.getString(colNote);
// Add the note
notes.add(note);
} while (cursor.moveToNext());
}
// Close the cursor
cursor.close();
}
Because you are fetching only integer and string from database, instead of using ArrayList , you can try using HashMap. So you can get the value by just giving the key. Below simple code will work for ArrayList too with minor changes..
Try this
HashMap<Integer,String> notes = new HashMap<Integer,String>() ;
Cursor cursor = db.rawQuery(GET_ALL_NOTES, null);
while (cursor.moveToNext())
{
int i = cursor.getInt(0);
String s = cursor.getString(1);
notes.put (i,s) ;
}
cursor.close();
I am storing messages from a chat group in a table dedicated to the group.
Now, any time I open this group in a listview, it displays the last N messages using this code:
public ArrayList<Post> getRecentPosts(int numOfMessagesGottenAlready,int numOfMessagesNeeded) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery("select * from "+ROOM_TABLE_NAME+ " LIMIT "+numOfMessagesNeeded +
" OFFSET (SELECT COUNT(*) FROM "+ROOM_TABLE_NAME+")-"+
(numOfMessagesGottenAlready + numOfMessagesNeeded)+";", null);
res.moveToFirst();
ArrayList<Post>posts = new ArrayList<>();
while (!res.isAfterLast()) {
posts.add(Post.parseJsonToPost(
res.getString(res.getColumnIndex(ROOMS_COLUMN_JSON))) );
res.moveToNext();
}
if (!res.isClosed()) {
res.close();
}
return posts;
}
Any time I need to load more messages into the group,I call the above method
which supplies the number of messages previously loaded as its first argument and the number of messages that need to be loaded as its second argument.
The method works well (or so I think), loading the messages from the bottom of the table upwards of course.
But there is an hitch.
When it gets to the top of the table i.e. OFFSET=0and then the method is called again,
the OFFSET becomes negative and so it just keeps loading the earliest messages at the top of the table as specified at https://www.sqlite.org/lang_select.html.
I want it to be that when the OFFSET evaluates to a value less than zero, then no value will be returned in the Cursor.
How do I modify the expression to achieve this please?
Okay, so I solved the problem by using 2 separate queries:
I wrapped the whole process described below in a transaction.
I first obtained the number of messages on the table. Then I checked using Java code if there were more messages to be loaded..and based on this result, I loaded more messages. So I was able to detect if I had gotten to the top of the table and write necessary code to return an empty list in that event:
Here is the code: it can be used to implement WhatsApp's LOAD EARLIER MESSAGES feature...where the loading is done from an sqlite table.
/**
* Very useful for loading a ChatRoom that already has messages loaded from the bottom of this
* table. It allows to 'load more' messages(just the number needed) without loading the
* whole ChatRoom.
* #param numOfMessagesGottenAlready The number of messages that the room has already.
* #param numOfMessagesNeeded The number of messages to load more.
* #return an ArrayList of messages loaded in pagination style..from the bottom this time.
*/
public ArrayList<Post> getRecentPosts(int numOfMessagesGottenAlready,int numOfMessagesNeeded) {
SQLiteDatabase db = this.getReadableDatabase();
int add = numOfMessagesGottenAlready + numOfMessagesNeeded;
boolean success = true;
try {
db.beginTransaction();
Cursor res = db.rawQuery("select COUNT(*) from "+ROOM_TABLE_NAME , null);
res.moveToFirst();
int count = res.getInt(0);
if (!res.isClosed()) {
res.close();
}
Log.e("table row count", count + "");
Log.e("add", add + "");
if(count >= numOfMessagesGottenAlready) {
Cursor set = db.rawQuery("select * from " + ROOM_TABLE_NAME + " ORDER BY " + ROOMS_COLUMN_ID +
" ASC LIMIT " + numOfMessagesNeeded +
" OFFSET ( " + (count - add) + " )"
, null);
set.moveToFirst();
ArrayList<Post>posts = new ArrayList<>();
try {
while (!set.isAfterLast()) {
posts.add(Post.parseJsonToPost(
set.getString(set.getColumnIndex(ROOMS_COLUMN_JSON))));
set.moveToNext();
}
}
catch (Exception e){return posts;}
if (!set.isClosed()) {
set.close();
}
return posts;
}
db.setTransactionSuccessful();
success = true;
}
catch (SQLiteException e){
e.printStackTrace();
success = false;
}
finally {
db.endTransaction();
}
return new ArrayList<Post>();
}
Thanks!
i am trying to pass dynamic id to query every time no of passed id will change sometimes it may be 3 or 2 or etc.My question is how can i pass this id and select values from query.
String[] splits = clickedTopicIdString.split("-");
Log.i("splits",""+splits.length); // length 2 bcoz clickedTopicIdString = 0-1 it may be 0-1-2 etc
if(splits.length > 0)
{
for(int i=0;i<splits.length;i++)
{clickedTopicIdInt = Integer.parseInt(splits[i]);// i want to save values in an array and pass it GetQuestionData(); this method after converting it in integer.....
Log.i("clickedTopicIdInt",""+clickedTopicIdInt);
}
}
clickedTopicIdInt = Integer.parseInt(clickedTopicIdString);
dbhelper = new JamiaBinoriaDBHelper(context);
dbhelper.open();
GetQuestionData();
This function will recieve id dynamically in form of arrays and will apply it here topic_question.topic_id="+topic_id1+" OR topic_question.topic_id="+topic_id2+" and so on how can i do this?
public List<String> GetClickedIdImages(int topic_id)
{ List<String> questionImageNameList = new ArrayList<String>();
String query = "SELECT topic_question.question_image_name FROM topic_question,topic WHERE topic_question.topic_id="+topic_id+" AND topic.id=topic_question.topic_id";
// Cursor cursor = db.rawQuery("SELECT topic_question.question_image_name FROM topic_question,topic WHERE topic_question.topic_id=1 AND topic.id=topic_question.topic_id",null);
Cursor cursor = db.rawQuery(query,null);
Log.i("Cursor Query Print:",""+query);
if(cursor != null) {
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
Log.d("cursor",""+cursor);
questionImageNameList.add(cursor.getString(0));
Log.i("cursor.getString(2)",""+cursor.getString(0));
cursor.moveToNext();
}
} else {
Log.d("", "Cursor is Null");
Log.d("retrieving all parameters", "count < 0");
}
cursor.close();
return questionImageNameList;
}
can someone please help me in this task ?
If you want to create your select dynamically basing on a list of IDs you shoud this SQL syntax:
SELECT * FROM TABLE WHERE ID IN (id1, id2, ..., idn)
id1,id2 = your ids
http://www.tutorialspoint.com/sqlite/sqlite_where_clause.htm
String numbers = "1-2-3-4-5";
String [] splits = numbers.split("-");
Integer [] realNumbers = new Integer [splits.length];
String sqlSelect = "SELECT * FROM TABLE WHERE ID IN ";
String whereStatement = "(";
for (int i = 0; i<splits.length; i++)
{
realNumbers[i] = Integer.parseInt(splits[i]);
whereStatement += realNumbers[i]+((i == splits.length -1) ? "" :",");
}
whereStatement += ");";
sqlSelect += whereStatement; //your select SELECT * FROM TABLE WHERE ID IN (1,2,3,4,5);