android SQLite database java.lang.IllegalStateException? - android

Hi i am using SQlite database for my app.
and i want to retrieve max value of increment primary key i.e ROWID.
but when i write query for this i got this exception
10-21 11:02:50.062: D/IllegalStateException(2575): java.lang.IllegalStateException: get field slot from row 0 col -1 failed
my method for retrieving max value is
public String getMaxID(){
SQLiteDatabase db = this.getReadableDatabase();
String productName = SingleTonClass.getInstance().dummy_productname;
String QUERY = "SELECT max("+ROW_ID+") as ID FROM "+TABLE_NAME
+" where "+PRODUCT_NAME+ " = " + "'" +productName+ "'";
Log.d("Query for Get previous cost", ""+QUERY);
Cursor maxID = db.rawQuery(QUERY, null);
String max = null;
int temp = 1;
try{
while(maxID.moveToNext()){
max = maxID.getString(maxID.getColumnIndex(ROW_ID));
Log.d("MaxID", ""+max);
maxID.close();
}
// }
// return max;
}catch(IllegalStateException e){
Log.d("IllegalStateException", ""+e);
}finally{
// maxID.close();
/ db.close();
}
return max;
}
Please help me out.
Thanks.

Problem is here
max = maxID.getString(maxID.getColumnIndex(ROW_ID));
Change to this
max = maxID.getString(maxID.getColumnIndex("ID"));

You are trying to get this column:
max = maxID.getString(maxID.getColumnIndex(ROW_ID));
But in your query you are using an alias:
"max("+ROW_ID+") as ID"
Try doing the following:
max = maxID.getString(maxID.getColumnIndex("ID")));
Hope it helps

Related

How to check if there is no same row in DB?

I have two method's in my SQLite Database in which i check if there is in a table certain column that is the same as a String after it i print all other columns on the same row and with the second method i check if a column from the first method equals to a data stored in a column of another table.
But i'm having issues when i check for a data that is not in the database here is an example:
TABLE CODART_BARCODE
CODART_CODART CODART_BARCODE CODART_PXC
123 1234 1
TABLE CODART_ART
DESCR_ART PVEN_ART PACQ_ART CODART_ART
PIZZ 1.50 12 123
So if in an EditText i insert 123 that equals to CODART_CODART and there is also 123 in CODART_ART from the other table i will print "PIZZ 1.50 12" but if i insert in the EditText 12356 the app crash because there is no same data in DB how can i prevent that app crash? i mean if there is no same data can i make a Toast that says "no data" or something like this but not making the app crash?
Here are the two methods from DB:
public String dbRawSearch(String id) {
StringBuilder dbString = new StringBuilder();
SQLiteDatabase db = this.getWritableDatabase();
String query = "SELECT * FROM " + TABLE_CODART + " WHERE CODART_BARCODE = " + id;
//Cursor points to a location in your results
#SuppressLint("Recycle") Cursor c = db.rawQuery(query, null);
//Move to the first row in your results
c.moveToFirst();
//Position after the last row means the end of the results
while (!c.isAfterLast()) {
if (c.getString(c.getColumnIndex("CODART_BARCODE")) != null) {
dbString.append(c.getString(c.getColumnIndex("CODART_CODART"))).append("\n");
dbString.append(c.getString(c.getColumnIndex("CODART_BARCODE"))).append("\n");
dbString.append(c.getString(c.getColumnIndex("CODART_PXC"))).append("\n");
}
c.moveToNext();
}
db.close();
return dbString.toString();
}
// FETCH codArt from Articoli
public String dbRawArticoli(String id){
StringBuilder dbString = new StringBuilder();
SQLiteDatabase db = this.getWritableDatabase();
String query = "SELECT * FROM " + TABLE_ART + " WHERE CODART_ART = " + id;
Cursor c = db.rawQuery(query, null);
c.moveToFirst();
while (!c.isAfterLast()) {
if (c.getString(c.getColumnIndex("CODART_ART")) != null) {
dbString.append(c.getString(c.getColumnIndex("DESCR_ART"))).append("\n");
dbString.append(c.getString(c.getColumnIndex("PVEN_ART"))).append("\n");
dbString.append(c.getString(c.getColumnIndex("PACQ_ART"))).append("\n");
}
c.moveToNext();
}
db.close();
return dbString.toString();
}
Your issue is that you are not correctly enclosing the search argument and thus if the value is non numeric then SQLite will consider that you are comparing a column, hence the no column found.
Lets say assuming you use :-
String result1 = yourdbHelper.dbRawSearch("123");
Then the resultant SQL will be :-
SELECT * FROM CODART WHERE CODART_BARCODE = 123;
That is fine as the search is looking for a number.
However if you used:-
String result1 = yourdbHelper.dbRawSearch("Fred");
Then the resultant SQL will be :-
SELECT * FROM CODART WHERE CODART_BARCODE = FRED
This would fail because FRED is non-numeric, and is therefore interpreted as saying SELECT all columns from the table CODART where the column named COADRT has the same value as the column named FRED, there is no column named FRED.
The result is that you get an error along the lines of :-
06-11 11:34:12.653 1373-1373/soanswers.soanswers E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{soanswers.soanswers/soanswers.soanswers.MainActivity}: android.database.sqlite.SQLiteException: no such column: FRED (code 1): , while compiling: SELECT * FROM CODART WHERE CODART_BARCODE = FRED
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
The Fix
The resolution is simple, and that is to enclose the argument being searched for in single quotes so that the SQL is then :-
SELECT * FROM CODART WHERE CODART_BARCODE = 'FRED'
Note that is just one example. However you will need to makes similar changes to both methods (dbRawSearch and dbRawArticoli), as shown :-
To do this you could change :-
String query = "SELECT * FROM " + TABLE_CODART + " WHERE CODART_BARCODE = " + id;
to :-
String query = "SELECT * FROM " + TABLE_CODART + " WHERE CODART_BARCODE = '" + id + "'";
and also change :-
String query = "SELECT * FROM " + TABLE_ART + " WHERE CODART_ART = " + id;
to :-
String query = "SELECT * FROM " + TABLE_ART + " WHERE CODART_ART = '" + id + "'";
Additional
However, there are SQLiteDatabase convenience methods that simplify building queries which also enclose/convert data accordingly.
One of these is the query method (as used in the following).
Rather than
moving to the first row and then
checking to see if you are then at the last row and then
using a moveToNext then going back to 2
in a do while loop, as all of the Cursor move??? methods return
true if the move could be made
otherwise false
you can simplify matters using :-
while(yourcursor.moveToNext) {
.... process the current row
}
As such the following methods could be considered
Note the 2 at the end of the method name is just to distinguish them from the originals
:-
public String dbRawSearch2(String id) {
StringBuilder dbString = new StringBuilder();
String whereclause = "CODART_BARCODE=?";
String[] whereargs = new String[]{id};
SQLiteDatabase db = this.getWritableDatabase();
Cursor c = db.query(TABLE_CODART,null,whereclause,whereargs,null,null,null);
while (c.moveToNext()) {
dbString.append(c.getString(c.getColumnIndex("CODART_CODART"))).append("\n");
dbString.append(c.getString(c.getColumnIndex("CODART_BARCODE"))).append("\n");
dbString.append(c.getString(c.getColumnIndex("CODART_PXC"))).append("\n");
}
c.close(); //<<<< Should always close cursors when finished with them
db.close();
return dbString.toString();
}
public String dbRawArticoli2(String id) {
StringBuilder dbString = new StringBuilder();
String whereclause = "CODART_ART=?";
String[] whereargs = new String[]{id};
SQLiteDatabase db = this.getWritableDatabase();
Cursor c= db.query(TABLE_ART,null,whereclause,whereargs,null,null,null);
while (c.moveToNext()) {
dbString.append(c.getString(c.getColumnIndex("DESCR_ART"))).append("\n");
dbString.append(c.getString(c.getColumnIndex("PVEN_ART"))).append("\n");
dbString.append(c.getString(c.getColumnIndex("PACQ_ART"))).append("\n");
}
c.close();
db.close();
return dbString.toString();
}
you should use wether your cursor is null or not and its size
if (c != null) {
if (c.getCount() > 0) {
return "your string";
}
}
return "";// In case no record found
In blank case give proper msg to the end user.
Change this part :
//Move to the first row in your results
c.moveToFirst();
//Position after the last row means the end of the results
while (!c.isAfterLast()) {
if (c.getString(c.getColumnIndex("CODART_BARCODE")) != null) {
dbString.append(c.getString(c.getColumnIndex("CODART_CODART"))).append("\n");
dbString.append(c.getString(c.getColumnIndex("CODART_BARCODE"))).append("\n");
dbString.append(c.getString(c.getColumnIndex("CODART_PXC"))).append("\n");
}
c.moveToNext();
}
To :
//Move to the first row in your results
if(c!= null && c.moveToFirst())
{
//Position after the last row means the end of the results
while (!c.isAfterLast()) {
if (c.getString(c.getColumnIndex("CODART_BARCODE")) != null) {
dbString.append(c.getString(c.getColumnIndex("CODART_CODART"))).append("\n");
dbString.append(c.getString(c.getColumnIndex("CODART_BARCODE"))).append("\n");
dbString.append(c.getString(c.getColumnIndex("CODART_PXC"))).append("\n");
}
c.moveToNext();
}
}
Explanation: In the case where there is no same data available you don't have the result set to get the string or column index from the result set.

SQLlite in android SUM select not working properly

I wanna get the sum of KEY_REC_VAL from table MMDatabaseHelper.TABLE_RECORD. My code is resulting in fatal error and I have no idea how to solve it. Any ideas? Thank you.
public Integer getIncomesSum()
{
String col = MMDatabaseHelper.TABLE_RECORD+"."+MMDatabaseHelper.KEY_REC_VAL;
String whereClause = " WHERE " +TABLE_RECORD+"."+KEY_REC_VAL+" >"+" 0";
String query = "SELECT sum ("+col+
") FROM "+TABLE_RECORD+
whereClause;
Log.i("SQL",query);
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = null;
try {
cursor = db.rawQuery(query,null);
} catch (SQLiteException e) {
} finally {
} return cursor.getInt(0);
Here is the error:
ERROR: android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 1
before return statement add this line cursor=cursor.moveToFirst();

How to insert a text with single quots to sqlite db in android?

I am facing an issue in inserting an issue in inserting a text with single quotes in sqlite db in android. it is returning the following error.
06-21 15:21:55.644: E/AndroidRuntime(16328): android.database.sqlite.SQLiteException: near
"re": syntax error (code 1): , while compiling: select * from tbl_chatHistory where
chat_date = '1.403344315631E12' and chat_time = '1.403344315635E12' and chat_text =
'you're'
Please help.
**************** EDITED *************************
public boolean checkChatExists(String date, String time, String chat) {
boolean result = false;
String selectQuery = "select * from tbl_chatHistory where chat_date = '"+date+"'
and chat_time = '"+time+"' and chat_text = '"+chat+"'";
SQLiteDatabase database = this.getWritableDatabase();
Cursor cursor = database.rawQuery(selectQuery, null);
if (cursor.moveToFirst()) {
result = true;
} else {
result = false;
}
cursor.close();
return result;
}
In SQL string literals you can escape ' as ''.
It however better to use parametrized queries. Replace the string literals with ? and provide the values in the bindArgs array. For example:
String selectQuery = "select * from tbl_chatHistory where chat_date = ? and chat_time = ? and chat_text = ?";
Cursor cursor = database.rawQuery(selectQuery, new String[] { date, time, chat });
Use ` instead of '. The problem is that the second ' is recognised as the end of the text.

How to use th SUM function to return the values from sqlite DB in android?

In my application, store the amount details of company in my sq lite DB.For example om my first position of DB in name column-company 1,total column - 400,second position of DB in name column-company 2,total column - 800,third position of DB in name column-company 1,total column - 500.how Sum the company 1 details only to return the total amount.
My main coding is,
String str = db.company_amount("Company 1");
Log.v("Total", ""+str);
My DB coding is,
String company_amount(String name){
SQLiteDatabase db = this.getReadableDatabase();
String s = "";
Cursor cursor = db.rawQuery("SELECT SUM(KEY_AMOUNT) FROM TABLE_BILL_DETAILS WHERE = ?", new String[] {String.valueOf(name)});
if (cursor != null) {
if (cursor.moveToNext()) {
s = cursor.getString(1);
return cursor.getString(1);
}
cursor.close();
}
return s;
}
It shows some error,I don't know how to return the values.Can any one know please help me to solve this problem.
My Logcat Error
04-25 14:54:06.701: E/AndroidRuntime(2776): FATAL EXCEPTION: main
04-25 14:54:06.701: E/AndroidRuntime(2776): java.lang.RuntimeException: Unable to start activity
ComponentInfo{invoicebill.details/invoicebill.details.Total_company_details}: android.database.sqlite.SQLiteException: near "=": syntax error: , while compiling: SELECT SUM(KEY_AMOUNT) FROM TABLE_BILL_DETAILS WHERE = ?
SQLiteDatabase db = getReadableDatabase();
String sql = "SELECT SUM(KEY_AMOUNT) FROM TABLE_BILL_DETAILS WHERE name = ?";
long sum = android.database.DatabaseUtils.longForQuery(db, sql, new String[]{name});
WHERE = ?
This is incorrect SQL syntax. You forgot to specify which field you're comparing with the argument. I guess it's name or something similar, so correct syntax would be something like:
WHERE name = ?
you can use to get details using id like this.
public int getTotalOfAmount(int id) {
odb = dbh.getReadableDatabase();
Cursor c = odb.rawQuery("SELECT SUM(" + KEY_AMOUNT + ") FROM " + DATABASE_TABLE + " WHERE " + KEY_ID + " = " + id, null);
c.moveToFirst();
int i = c.getInt(0);
c.close();
return i;
}
.

SQLite: How to get average of long type values

I'm making an app that records the timestamp of touchscreen actions made my the user.
Then, after recording the readings in an SQLite table, I take the average of each column at the end. However, I'm getting an error:
E/AndroidRuntime(1344): java.lang.NumberFormatException: Invalid long: "1.40024e+08"
This happens when I try to take the average of each column, which I'm doing like so:
public long[] getAvg()
{
String selectQuery = "SELECT AVG(dwell_1), AVG(dwell_2), AVG(dwell_3), AVG(dwell_4), AVG(dwell_5), AVG(dwell_6), AVG(dwell_7), AVG(dwell_8), AVG(dwell_9), AVG(flight_12), AVG(flight_23), AVG(flight_34), AVG(flight_45), AVG(flight_56), AVG(flight_67), AVG(flight_78), AVG(flight_89) FROM " + TABLE;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
long[] row = new long[17];
if (cursor.moveToFirst()) {
for (int j=0; j<17; j++)
row[j] = Long.parseLong(cursor.getString(j));
}
return row;
}
It seems to be a function of the way the SQLite query displays the results. Is there any way I can circumvent/solve this? I require the precision by the way, so I can't use int or something else instead.
Oddly enough, when I run a query to just straight up display every record in the table, it works fine.
Any help will be greatly appreciated. Thanks in advance!
I believe SQLiteAVG() function returns a float value which you are trying to parse it as Long, hence the exception.
Try this :
public long[] getAvg()
{
String selectQuery = "SELECT AVG(dwell_1), AVG(dwell_2), AVG(dwell_3), AVG(dwell_4), AVG(dwell_5), AVG(dwell_6), AVG(dwell_7), AVG(dwell_8), AVG(dwell_9), AVG(flight_12), AVG(flight_23), AVG(flight_34), AVG(flight_45), AVG(flight_56), AVG(flight_67), AVG(flight_78), AVG(flight_89) FROM " + TABLE;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
long[] row = new long[17];
if (cursor.moveToFirst()) {
for (int j=0; j<17; j++)
row[j] = cursor.getLong(j);
}
return row;
}
SQLite returns float result, which you are trying to save to long.
Possible solutions:
Use float/double variables on Java side.
Or force SQLite to output integer/long using
SELECT CAST(avg(field) AS INTEGER) AS avg_field...
In your case, result should still fit into Java long if original was SQLite INTEGER.
Consider a simple method that fetches the average rating of an entity. The rating float value is stored between 0.0 to 5.0.
public static float getAverageReviews(SQLiteDatabase db) {
String selectQuery = "SELECT SUM(stars) * FROM " + DatabaseHelper.TABLE_STORE_REVIEWS;
Cursor c = db.rawQuery(selectQuery, null);
int count = c.getCount();
float totalSum = 0;
if(count > 0 && c.moveToFirst())
{
do {
String result = c.getString(c.getColumnIndex(StoreReviews.KEY_STARS));
totalSum += Float.parseFloat(result);
} while (c.moveToNext());
}
else {
return 0;
}
return totalSum/count;
}

Categories

Resources