Have a very strange issue with pulling data from SQLite Database on Android. Here is my method that takes all the entries from the table entries and iterates them through the loop, putting them in the list view.
It works fine until I wanted to change this line
Cursor c = readableDatabase.rawQuery("select * from entries", null);
to this one:
Cursor c = readableDatabase.rawQuery("select * from entries order by ID DESC", null);
So after the change I don't see the first element. Not sure what is going there. Here is the source code of that method.
EntryHelper entryHelper = new EntryHelper(this);
SQLiteDatabase readableDatabase = entryHelper.getReadableDatabase();
// NOTE: needs to be changed to order by ID...
//
Cursor c = readableDatabase.rawQuery("select * from entries", null);
c.moveToFirst();
ArrayList productsList = new ArrayList();
ProductsArrayAdapter productsArrayAdapter = new ProductsArrayAdapter(this, productsList);
while (c.moveToNext()) {
Integer entryIdIndex = c.getColumnIndexOrThrow(Schema.Entry.ID);
Integer entryBarcodeIndex = c.getColumnIndexOrThrow(Schema.Entry.COLUMN_NAME_BARCODE);
Integer entryQuantityIndex = c.getColumnIndexOrThrow(Schema.Entry.COLUMN_NAME_QUANTITY);
Integer entryId = c.getInt(entryIdIndex);
String entryBarcode = c.getString(entryBarcodeIndex);
String entryQuantity = c.getString(entryQuantityIndex);
Product lineItemProduct = new Product(entryId, entryBarcode, entryQuantity);
productsList.add(lineItemProduct);
Toast toast = Toast.makeText(this, lineItemProduct.toString(), Toast.LENGTH_SHORT);
toast.show();
}
productsListView = (ListView) findViewById(R.id.productsList);
productsListView.setAdapter(productsArrayAdapter);
Any help will be appreciated
This is your problem:
c.moveToFirst();
// other code
while (c.moveToNext()) {
Your skipping the first element, moveToFirst puts your cursor at the first position, then your while moves one more position to the second position.
Either remove the moveToFirst() (you aren't checking the return type or doing anything with this anyway). Or change your while loop to a do while but this assumes you always have at least 1 result. I recommend removing c.moveToFirst.
Related
I don't know what's wrong with my code I follow the rule but I get wrong result. I want to search db and find all rows data but I only get last row from sqlite. my code to search database is bellow:
public ArrayList<ArrayList<ContractSaveDataFromDB>> ActiveContractData(String phone, String numberId)
{
ArrayList<ContractSaveDataFromDB> UserData = new ArrayList<ContractSaveDataFromDB>();
ArrayList<ArrayList<ContractSaveDataFromDB>> SendUserData =
new ArrayList<ArrayList<ContractSaveDataFromDB>>();
SQLiteDatabase db = this.getReadableDatabase();
String whereClause = "phone = ? AND numberId = ?";
String[] whereArgs = new String[]{
phone,
numberId
};
String orderBy = "activeContract";
Cursor res2=db.query("usersAccount",null,whereClause,whereArgs,null,null,orderBy);
res2.moveToFirst();
do{
UserData.clear();
int index;
ContractSaveDataFromDB contractSaveDataFromDB=new ContractSaveDataFromDB();
index = res2.getColumnIndex("buyAmount");
String buyAmount = res2.getString(index);
contractSaveDataFromDB.setBuyAmount(buyAmount);
UserData.add(contractSaveDataFromDB);
SendUserData.add(UserData);
} while(res2.moveToNext());
res2.close();
db.close();
return SendUserData;
I don't know what's wrong. I appreciate if you help me to solve my problem.
you already added where clause so maybe it is filtering your results try to remove it by change this
Cursor res2=db.query("usersAccount",null,whereClause,whereArgs,null,null,orderBy);
to this
Cursor res2=db.query("usersAccount",null,null,null,null,null,orderBy);
I believe that your issues is that you are trying to use an ArrayList of ArrayList of ContractSaveDataFromDB objects.
I believe that an ArrayList of ContractSaveDataFromDB objects would suffice.
It would also help you if you learnt to do a bit of basic debugging, as an issue could be that you are not extracting multiple rows.
The following is an alternative method that :-
uses the ArrayList of ContractSaveDataFromDB objects,
introduces some debugging by the way of writing some potentially useful information to the log
and is more sound, as it will not crash if no rows are extracted
i.e. if you use moveToFirst and don't check the result (false means the move could not be accomplished) then you would get an error because you are trying to read row -1 (before the first row) as no rows exists in the cursor.
:-
public ArrayList<ContractSaveDataFromDB> ActiveContractData(String phone, String numberId) {
ArrayList<ContractSaveDataFromDB> SendUserData = new ArrayList<ContractSaveDataFromDB>();
SQLiteDatabase db = this.getReadableDatabase();
String whereClause = "phone = ? AND numberId = ?";
String[] whereArgs = new String[]{
phone,
numberId
};
String orderBy = "activeContract";
Cursor res2 = db.query("usersAccount", null, whereClause, whereArgs, null, null, orderBy);
Log.d("RES2 COUNT", "Number of rows in Res2 Cursor is " + String.valueOf(res2.getCount()));
while (res2.moveToNext()) {
ContractSaveDataFromDB current_user_data = new ContractSaveDataFromDB();
current_user_data.setBuyAmount(res2.getString(res2.getColumnIndex("buyAmount")));
Log.d("NEWROW", "Adding data from row " + String.valueOf(res2.getPosition()));
SendUserData.add(current_user_data);
}
res2.close();
db.close();
Log.d("EXTRACTED", "The number of rows from which data was extracted was " + String.valueOf(SendUserData.size()));
return SendUserData;
}
If after running you check the log you should see :-
A line detailing how many rows were extracted from the table
A line for each row (if any were extracted) saying Adding data from row ? (where ? will be the row 0 being the first)
A line saying The number of rows from which data was extracted was ? (? will be the number of elements in the array to be returned)
I am trying to display value of a particular row in android to check if a particular updation. Can I made it successful or not? But as the return type is cursor I don't know how to fetch it. So pls help me.
public Cursor getData(int id) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery("select * from calls where id=" + id + "", null);
return res;
}
Try this...
ArrayList<HashMap<String, String>> dataList = new ArrayList<>();
call your method to get data as arraylist of hashmap
dataList.addAll(loginDataBaseAdapter.getData(id));
or
dataList = loginDataBaseAdapter.getData(id);
in db_class
public ArrayList<HashMap<String, String>> getData(String id) {
ArrayList<HashMap<String, String>> returnArray = new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery("select * from calls where id=" + id + "", null);
if (res != null && res.getCount() > 0) {
if (res.moveToLast()) {
do {
HashMap<String, String> getdatamap = new HashMap<String, String>();
getdatamap.put("KEY_ONE", res.getString(1));
getdatamap.put("KEY_TWO, res.getString(2));
returnArray.add(getdatamap);
}while (res.moveToPrevious());
}
}
res.close();
return returnArray;
}
Now you can use the values in arraylist to make your view
You can follow the below code:
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery("select * from calls where id=" + id + "", null);
if (res != null) {
res.moveToFirst();
}
String firstColumnValue = res.getString(0);
String secondColumnValue = res.getString(1);
And close the database after retrieving values:
db.close();
If you want to get column value by its name, then use the following code:
String value = res.getColumnIndex("column_name");
Get row value as a String. Then return string value.
public String getData(int id) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor res = db.rawQuery("select * from calls where id=" + id + "", null);
if (res.getCount() > 0) {
res.moveToFirst();
String s = res.getString(res.getColumnIndex("id"));
return s;
}
There are two factors that need to be considered when retrieving data from a cursor; which row (position within the cursor) and then column and it's type.
To position the Cursor you use one of the Cursor's move methods. These are :-
move, which moves the cursor relevant to it's current position.
moveToFirst
moveToLast
moveToNext
moveToPosition and
moveToPrevious
All return true if the move could be performed otherwise false.
A cursor can be empty and have no rows, so movetoFirst would return false.
One of the more common usages is :-
while (cursor.moveToNext) {
.... cursor action(s) here.
}
A Cursor will initially be positioned to before the first row i.e. it's position is -1 and can be set using moveToPosition(-1).
The Cursor's getPosition method will retrieve the current position, noting that the first row is position 0.
Column's in rows are accessed according to the offset (which column) and the Cursor's get???? (where ???? represents type) methods are used to retrieve the data from the row/column (there are other get.... methods e.g. getPosition as above). The methods for retrieving the data are:-
getBlob (retrieves a byte array).
getDouble
getFloat
getInt
getLong
getShort
getString
All take a single parameter, an integer that is the column's offset within the cursor (which is not necessarily the offset in the table).
You can use any on any type of data, with the exception of blobs. An attempt to use any, except getBlob, on a BLOB will result in an exception.
However, the results, can vary e.g. if you use get, for example assuming column with offset 0 contains *rumplestilskin then :-
cursor.getString(0) will return rumplestiltskin
cursor.getDouble(0) will return 0 as a double.
cursor.getInt(0) will return 0 as a float.
.....
In short, you should use the appropriate get method, otherwise the results could be confusing.
Hard coding column column offsets, often results in issues therefore it is generally better to use column names in conjunction with the Cursor's getColumnIndex method. This takes a String, the column name, as a parameter and returns the offset of the column.
Applying the above to the question:-
Code that could be useful (i.e. it retrieves data) could be :-
Cursor csr = db.getData(myid);
while (csr.moveToNext) {
long id_of_the_row = csr.getLong(csr.getColumnIndex(yourDatabaseHelperClass.id));
}
Noting:-
if (moveToFirst(myid)) { .... } could be considered more correct but assuming that just a single row exists bot moveToFirst and moveToNext, as coded, produce the same result.
Assuming that the id column is an alias of the rowid, then rowid is stored as a long and should properly be extracted as a long.
yourDatabaseHelperClass.id will not be correct, rather you would replace it with the class that extends SQLiteOpenHelper (the class that contains your getData method), it also assumes that variable id has public access.
Links that may be useful or of interest:-
Cursor
How flexible/restricive are SQLite column types?
(includes examples of how some of the Cursor get???? methods retrieve data)
Are there any methods that assist with resolving common SQLite issues?
I have setup an application which currently can lookup an input id with one on the database to then give a single result. E.g. user enters id = 1 , database contains a record with an id of 1 then returns the name or number etc...
Now I want to improve the system slightly by querying my database with an arraylist which contains a range of id's e.g. 3, 456, 731 etc... which I want my database to search for. I have also grouped multiple values to certain id's for example the database might search for an id of 3 it will then find 5 results I want it to return the telephone number of each one of those results into another arraylist which I can print to the logs.
I hope I have explained this enough, but please ask questions if you require more information.
The code below demonstrates the modified version of the query used to gain a single result, but I cannot see what I'm doing wrong to gain multiple results.
Activity....
// New array list which is going to be used to store values from the database
ArrayList<String> contactsList;
// This arrayList has been received from another activity and contains my id's
ArrayList<String> contacts = intent.getStringArrayListExtra("groupCode");
// The database which i'm using
ContactDBHandler contactDBHandler = new ContactDBHandler(getApplicationContext(), null, null, 1);
//getAllValues is used to pass my arraylist id's to the database.
contactsList = contactDBHandler.GetAllValues(contacts);
// Simple log statement to loop and display results
for (int i = 0; i < contactsList.size(); i++){
Log.i("Numbers", contactsList.get(i));
}
ContactDBHandler
Query
// I'm telling it to get the contact number from the contact_list
// when the groupcode matches the code recieved.
public ArrayList<String> GetAllValues(ArrayList groupCode)
{
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = null;
String alarmName = "";
ArrayList<String> list = new ArrayList<>();
cursor = db.rawQuery("SELECT contact_number FROM contact_list WHERE grp_code=?", new String[]{groupCode+ ""});
if (cursor.moveToFirst())
{
do
{
list.add(cursor.getString(0));
}
while (cursor.moveToNext());
}
if (cursor != null && !cursor.isClosed())
{
cursor.close();
}
return list;
}
Thanks
Can you see where I have gone wrong?
Try this:
cursor = db.rawQuery("SELECT contact_number FROM contact_list WHERE grp_code IN (" + TextUtils.join(",", Collections.nCopies(groupCode.size(), "?")) + ")", groupCode.toArray(new String[groupCode.size()]));
Your current code fails to pass the list in the sql-format: = does only support single values, for lists you have to use IN.
Your code would result in a query like this:
SELECT contact_number FROM contact_list WHERE grp_code=["some_id","other_id"]
But what you need (and my code produces) is:
SELECT contact_number FROM contact_list WHERE grp_code IN ('some_id','other_id')
References:
SQL query to find rows with at least one of the specified values
WHERE IN clause in Android sqlite?
IN clause and placeholders
https://developer.android.com/reference/android/text/TextUtils.html#join(java.lang.CharSequence,%20java.lang.Iterable)
You cannot pass an ArrayList to an SQLQuery. To check for multiple values in the same field you have to use the 'in' keyword.
Ex:
SELECT * FROM `table1` where column in ( 'element1', 'element2', 'element3')
In your case,
String str = "";
for(String s: groupCode){
str = str+","+"\'"+s+"\'";
}
//to remove the extra ' in the begining
str = str.substring(1);
return str;
cursor = db.rawQuery("SELECT contact_number FROM contact_list WHERE grp_code IN (?)", new String[]{str});
I have an android project, with a database where entries are logged as pairs with the same ID.
I have two for loops, one to get all entries of a certain ID, and one to get all entries in the table. These are then automatically populated into a listview.
The problem I have is that the program crashes when I attempt to use the forloop that gets all entries from the database, but it works perfectly fine when I use the for loop that wants all entries with the same ID. I have been commenting out the for loop im not using.
The for loops:
List<Assignment> list = db.getPickupDelivery(1);
for (int i = 0; i < list.size();i++)
{
allDeliveries.add(list.get(i));
}
List<Assignment> list = db.getAllAssignments();
for (int i = 0; i < list.size();i++)
{
allDeliveries.add(list.get(i));
}
The methods they call:
public List<Assignment> getPickupDelivery(int i) {
List<Assignment> assignments = new LinkedList<Assignment>();
//bygg query
String query = "SELECT * FROM " + TABLE_ASSIGNMENTS + " WHERE id = " + i;
//fa referens
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(query, null);
//iterera och bygg och lagg till
Assignment assignment = null;
if (cursor.moveToFirst()) {
do {
assignment = new Assignment();
assignment.setID(Integer.parseInt(cursor.getString(0)));
assignment.setType(cursor.getString(1));
assignment.setSenderreceiver(cursor.getString(2));
assignment.setAdress(cursor.getString(3));
assignment.setTime(cursor.getString(4));
assignment.setZipcode(cursor.getString(5));
assignment.setContact(cursor.getString(6));
assignment.setPhone(cursor.getString(7));
assignment.setInstructions(cursor.getString(8));
//lagg till
assignments.add(assignment);
} while (cursor.moveToNext());
}
cursor.close();
Log.d("getPickupDelivery()", assignments.toString());
return assignments;
}
public List<Assignment> getAllAssignments() {
List<Assignment> assignments = new LinkedList<Assignment>();
//bygg query
String query = "SELECT * FROM " + TABLE_ASSIGNMENTS;
//fa referens
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(query, null);
//iterera och bygg och lagg till
Assignment assignment = null;
if (cursor.moveToFirst()) {
do {
assignment = new Assignment();
assignment.setID(Integer.parseInt(cursor.getString(0)));
assignment.setType(cursor.getString(1));
assignment.setSenderreceiver(cursor.getString(2));
assignment.setAdress(cursor.getString(3));
assignment.setTime(cursor.getString(4));
assignment.setZipcode(cursor.getString(5));
assignment.setContact(cursor.getString(6));
assignment.setPhone(cursor.getString(7));
assignment.setInstructions(cursor.getString(8));
//lagg till
assignments.add(assignment);
} while (cursor.moveToNext());
}
cursor.close();
Log.d("getAllAssignments()", assignments.toString());
return assignments;
}
The error I get at the time of the crash is a an error that says "...MainActivity}: java.lang.NumberFormatException: Invalid int: "null""
My guess is that in your database definition, you didn't specify the ID column as INTEGER NOT NULL. So when you select every row, one or more of those rows has a null ID, which you're trying to parse as an int here:
assignment.setID(Integer.parseInt(cursor.getString(0)));
Change your database definition to require that the ID column is not null. You'll need to uninstall or clear data on your app so the database is recreated.
Also another tip - Android's SQLITE implementation will enforce that you have a column called "_id", so I'd suggest using that, not "id". Otherwise you'll end up with an extra column you don't need.
In your code:
assignment.setID(Integer.parseInt(cursor.getString(0)));
if cursor.getString(0) returns null, then Integer.parseInt(String str) will throw NumberFormatException.
Check this line or you can use try-catch and print the appropriate message in catch if you'll get NumberFormatException.
The exception is the hint. It says that a string null is being parsed as a number and this fails.
In your code there the place where it happens is:
assignment.setID(Integer.parseInt(cursor.getString(0)));
First you get a string from the cursor and then you pass it to Integer.parseInt for parsing.
So the cause of the problem is that you expect there to be no null values in the first column but there is at least one.
Also, your code is unnecessarily complex and inefficient. Instead of Integer.parseInt(cursor.getString(0)) you could write cursor.getInt(0) to directly get an int. This is also likely to throw an error on the null value though (but the error message might be more informative).
I am just trying to search for the data in multiple table.If the where condition data is not present in first table(tab1) then it has to search in the second table(tab2) but I am getting the exception showing that
Cursor Index Out of Bounds Exception: Index -1 requested with size 0
Here is my code
SQLiteDatabase db=openOrCreateDatabase("train",SQLiteDatabase.CREATE_IF_NECESSARY, null);
Cursor c1;
String[] table={"tab1","tab2","tab3","tab4"};
int i=0;
do {
c1 = db.rawQuery("select * from '"+table[i]+"' where name='Triplicane'", null);
i++;
} while(c1 == null);
int id1=c1.getInt(0);
String nam1=c1.getString(1);
Toast.makeText(fare.this,"ID no:"+id1, Toast.LENGTH_LONG).show();
Toast.makeText(fare.this,"name"+nam1, Toast.LENGTH_LONG).show();
So from the beginning. Implicitly, each Cursor is positioned before first row so if you want to work with it you need to call
cursor.moveToFirst()
that moves Cursor to first row if is not empty and then is ready for work. If Cursor is empty simply it returns false. So how i mentioned now this method is very handy indicator whether your Cursor is valid or not.
And as my recommendation i suggest you to change your code because i think is broken and it sounds like "spaghetti code"
Cursor c = null;
String[] tables = {"tab1", "tab2", "tab3", "tab4"};
for (String table: tables) {
String query = "select * from '" + table + "' where name = 'Triplicane'";
c = db.rawQuery(query, null);
if (c != null) {
if (c.moveToFirst()) { // if Cursor is not empty
int id = c.getInt(0);
String name = c.getString(1);
Toast.makeText(fare.this, "ID: " + id, Toast.LENGTH_LONG).show();
Toast.makeText(fare.this, "Name: " + name, Toast.LENGTH_LONG).show();
}
else {
// Cursor is empty
}
}
else {
// Cursor is null
}
}
Notes:
Now i want to tell you some suggestions:
An usage of parametrized statements is very good practise so in a
future if you will work with statements, use placeholders in them. Then your statements becomes more human-readable, safer(SQL Injection) and faster.
It's also a very good practise to create static final fields that will hold
your column names, table names etc. and to use
getColumnIndex(<columnName>) method to avoid "typo errors" which are looking for very bad.
Your Cursor flag to empty row , On Sqlite cursor pointed to row number -1 ,
then if you use c.moveNext() or c.moveToFirst() you'll be able to read rows "row by row "
write cursor.movetoFirst() before getting data from cursor.