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.
Related
I am working on a SQLite program and getting an error saying
2019-07-14 21:07:37.465 13538-13538/? E/CursorWindow: Failed to read row 0, column -1 from a CursorWindow which has 1 rows, 2 columns.
2019-07-14 21:07:37.466 13538-13538/? D/AndroidRuntime: Shutting down VM
2019-07-14 21:07:37.467 13538-13538/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.xyz.sqlitelist, PID: 13538
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.xyz.sqlitelist/com.example.xyz.sqlitelist.MainActivity}: java.lang.IllegalStateException:
Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
.
.
Caused by: java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
W/ActivityManager: Force finishing activity com.example.xyz.sqlitelist/.MainActivity
String databaseToString(){
StringBuilder dbString= new StringBuilder();
SQLiteDatabase db = getWritableDatabase();
String query=" SELECT * FROM " + TABLE_PRODUCTS + " WHERE 1";
Cursor c=db.rawQuery(query,null);
c.moveToFirst();
while (!c.isAfterLast()){
if(c.getString(c.getColumnIndex("productname")) != null) {
c.moveToNext();
dbString.append(c.getString(c.getColumnIndex("productname")));
dbString.append("\n");
}
c.close();
db.close();
return dbString.toString();
}
Your column's name is "_productname" and not "productname" and this problem can be solved by not hardcoding this name since you have it in the variable COLUMN_PRODUCTNAME.
Also your code will miss rows because you use incorrectly moveToFirst(), moveToNext() and isAfterLast() when you only need moveToNext():
String databaseToString() {
StringBuilder dbString = new StringBuilder();
SQLiteDatabase db = getWritableDatabase();
String query = "SELECT * FROM " + TABLE_PRODUCTS + " WHERE 1";
Cursor c = db.rawQuery(query, null);
int index = c.getColumnIndex(COLUMN_PRODUCTNAME);
while (c.moveToNext()) {
dbString.append(c.getString(index)).append("\n");
}
c.close();
db.close();
return dbString.toString();
}
Also that WHERE 1 in the sql statement is not needed unless you want to change it later to something meaningful.
you can change your code
String sql = " SELECT * FROM " + TABLE_PRODUCTS + " WHERE 1";
Cursor c = getWritableDatabase().rawQuery(sql, null);
while (c.moveToNext()) {
if(c.getString(c.getColumnIndex("productname")) != null)
{
dbString.append(c.getString(c.getColumnIndex("productname")));
dbString.append("\n");
}
}
c.close();
db.close();
return dbString.toString();
I have a table and I want to update the existing values when the count is greater is 1.
Here is my code :
public int getCount(String clues) {
Cursor c = null;
try {
db = this.getReadableDatabase();
String query = "select count(*) from " + TABLE_NAME + "where CLUES_VALUES = ?";
c = db.rawQuery(query, new String[] {clues});
if (c.moveToFirst()) {
return c.getInt(0);
}
return 0;
}
finally {
if (c != null) {
c.close();
}
if (db != null) {
db.close();
}
}
}
I am checking based on the column "CLUES_VALUES" . I am getting the values from database and checking if it contains more than one similar value in the column of "CLUES_VALUES" . If it contains then it will update the entire row else it won't.
when I am executing the code, I am getting below error
android.database.sqlite.SQLiteException: near "=": syntax error (code 1): , while compiling: select count(*) from puzzl_tablewhere CLUES_VALUES = ?
Clues_values column contains "String values"
I don't know where I am missing. Please help .
You're missing a space in front of "where".
String query = "select count(*) from " + TABLE_NAME + " where CLUES_VALUES = ?";
I think what you are missing is simply a space after table name and before where.
String query = "select count(*) from " + TABLE_NAME + " where CLUES_VALUES = ?";
This is my query :
Cursor nextdate(String Date) {
SQLiteDatabase db = this.getReadableDatabase();
String[] params = new String[]{String.valueOf(Date)};
Cursor cur = db.rawQuery(" SELECT MIN (" + colDateDue + ") FROM " + PAYMENTS + " WHERE " + colDateDue + ">=?", params);
cur.moveToFirst();
return cur;
}
I want to display the result of that query in a TextView but I don't know how to, so naturally I look for an answer. I find a few answers around and come up with this :
DatabaseHelper db = new DatabaseHelper(this);
String str = "";
if (c!= null) {
if (c.moveToFirst()) {
str = c.getString(c.getColumnIndex(db.colDateDue);
}
}
TextView.setText(str);
But I get the error
Caused by: java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
Which got me a bit confused since the usual fix for that error is using cur.moveToFirst(); which is used in both instances... what am I doing wrong exactly?
try like this:
keep the column index as 0 because that cursor will have only one column.
DatabaseHelper db = new DatabaseHelper(this);
String str = "";
if (c!= null) {
if (c.moveToFirst()) {
str = c.getString(0);
}
}
TextView.setText(str);
You are attempting to use the index of db.colDateDue. However, that does not correlate with your actual query. You can happily pull the first result with:
str = c.getString(0);
I wrote one query which select the name and designation fields based on id and then in fragment class i am calling that method which belongs to the appropriate query but unfortunately i am getting Sqlite Exception.
Database Method
public Employee getEmployeeName(int id) {
SQLiteDatabase db = this.getWritableDatabase();
Employee employee = new Employee();
String query ="SELECT " + KEY_NAME +", " +KEY_DESIG +" FROM " + TABLE_EMPLOYEES+ " WHERE " + KEY_ID + "=" + id;
Cursor cursor = db.rawQuery(query, null);
if (cursor.moveToFirst()) {
do {
employee.setName(cursor.getString(1));
employee.setDesignation(cursor.getString(2));
} while (cursor.moveToNext());
}
return employee;
}
Calling from the Fragment
db.getEmployeeName(selectedManager);
Exception
01-07 06:02:34.185: E/AndroidRuntime(2386): java.lang.IllegalStateException: Couldn't read row 0, col 2 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
Column indexes are zero-based. getString(2) refers to the third column and your cursor has only two columns.
Change
employee.setName(cursor.getString(1));
employee.setDesignation(cursor.getString(2));
to
employee.setName(cursor.getString(0));
employee.setDesignation(cursor.getString(1));
try this
if (cursor.moveToFirst()) {
do {
employee.setName(cursor.getString(cursor.getColumnIndex(KEY_NAME));
employee.setDesignation(cursor.getString(cursor.getColumnIndex(KEY_DESIG));
} while (cursor.moveToNext());
}
Get data from Cursor by using cursor.getColumnIndex(COLUMN NAME)
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;
}
.