If you look at my code at the bottom, I have database with column 'used'. If it's 1 it means that it haven't been used, when it is used it set to update the number to 0. But when all of the rows have used number 0, that I would like to update used from 0 to 1 again. How to do that? I do not have a clue. Tried with cd.getCount() but did not work, try some other stuff too but again could not managed to get it to work. So I asking if anyone can help me and tell me what to put into code. Thank you!
This is the error I am getting:
02-25 18:46:16.962: E/AndroidRuntime(9728): android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
public void set(){
SQLiteDatabase db;
String vprasanje = "";
db=openOrCreateDatabase("baza.db",MODE_PRIVATE, null);
Cursor cd=db.rawQuery("SELECT * FROM vprasanja WHERE kategorija=" + kategorija4 + " AND used = 1 ORDER BY RANDOM() LIMIT 1", null);
cd.moveToFirst();
vprasanje = cd.getString(cd.getColumnIndex("text"));
//patch
String id2 = (cd.getString(cd.getColumnIndex("id")));
int idd2 = Integer.parseInt(id2);
db.execSQL("UPDATE vprasanja SET used=0 WHERE id =" + idd2 + ";");
beseda = (TextView) findViewById(R.id.textView3);
beseda.setText("");
beseda.setText(vprasanje);
db.close();
busy = 0;
}
Ok, so there are a couple of things in your code that need to be fixed. First, you need to check if cursor.moveToFirst() actually happened. You can't try to get strings if there are no records in the database.
First thing then:
if(cd.moveToFirst()){
vprasanje = cd.getString(cd.getColumnIndex("text"));
//patch
String id2 = (cd.getString(cd.getColumnIndex("id")));
int idd2 = Integer.parseInt(id2);
db.execSQL("UPDATE vprasanja SET used=0 WHERE id =" + idd2 + ";");
beseda = (TextView) findViewById(R.id.textView3);
beseda.setText("");
beseda.setText(vprasanje);
db.close();
busy = 0;
}
However, as long as you dont insert stuff into the database, this will always be false, because there will never be any records in your database. You'll want to insert stuff in case you can't update it:
db.rawQuery("INSERT INTO .... SET ... VALUES ...");
Related
I am getting an error in Android Studio to do with my Cursor.
I have the following line in my code
String data = cursor.getString(cursor.getColumnIndex(columnIndex));
columnIndex is being passed into the method.
This part cursor.getColumnIndex(columnIndex) produces the following error
Value must be ≥ 0
Its happening in my DBHelper class and also my recycler adapter when it uses a cursor too.
It shows up as an error in red but the app still builds and runs without issue.
Any ideas?
Thanks for any help.
Update 22-Sep-21
I'm adding some code as requested and also how i have got around this error. Not sure if its the best way though.
So the method im using is this....
public String getTripInfo(String tableName, int tripNo, String columnIndex){
String data = "";
// Select all query
String selectQuery = "SELECT * FROM " + tableName + " WHERE " + TRIP_DETAILS_TRIP_NUMBER + "=" + tripNo;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// Looping through all rows and adding to list
if(cursor.moveToFirst()){
do{
data = cursor.getString(cursor.getColumnIndex(columnIndex));
} while(cursor.moveToNext());
}
// Closing connections
cursor.close();
db.close();
//Returning number plates
return data;
}
The error is in the do while loop. The part in red is "cursor.getColumnIndex(columnIndex))"
The way i have gotten around this error is using the following code instead
public String getTripInfo(String tableName, int tripNo, String columnIndex){
String data = "";
// Select all query
String selectQuery = "SELECT * FROM " + tableName + " WHERE " + TRIP_DETAILS_TRIP_NUMBER + "=" + tripNo;
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
// Looping through all rows and adding to list
if(cursor.moveToFirst()){
do{
int index = cursor.getColumnIndex(columnIndex);
data = cursor.getString(index);
} while(cursor.moveToNext());
}
// Closing connections
cursor.close();
db.close();
//Returning number plates
return data;
}
I had an error like this.
My solution : change method getColumnIndex into getColumnIndexOrThrow.
The problem is that cursor.getColumnIndex() can return -1, you're passing it as a direct parameter, and the cursor getters need a column index gte 0. The getters' parameter is annotated with #IntRange(from = 0) which is why lint marks it as an error.
So, even though you might have built your project such that it would never produce an invalid column index, the fact that such a possibly could exist is why lint is tagging it.
Your code revision only avoids the issue. It would be best to use cursor.getColumnIndexOrThrow() or test index for gte 0.
You can get away with your changes since you know more about your project than lint does, it just isn't the best practice.
Use This Method Proper Work :-
#SuppressLint("Range") Strong name = cursor.getString(cursor.getColumnIndex(indexNumber));
I am using below query to update the column. Now what I want that I want to update these columns only when it is empty or null. How can I achieve this ?
db.execSQL("UPDATE FieldTestDataTemp SET
Image1 = '" + f10.image1 + "',
Image2 = '" + f10.image2 + "',
Image3 = '" + f10.image3 + "',
Image4 = '" + f10.image4 + "',
Image5 = '" + f10.image5 + "',
starRating = '" + starRating1 + "' ");
In mysql we used to use this query
UPDATE table
SET field = 'Your value'
WHERE field
IS NULL
OR LENGTH(field)=0
You have to set multiple query to set multiple column condition.
You can pass parameters like this to a common method that will return you the number of records updated
public int updateRecords(String table, ContentValues values,
String whereClause, String[] whereArgs) {
int a = db.update(table, values, whereClause, whereArgs);
return a;
}
and in this db is SQLiteDatabase object
private SQLiteDatabase db;
According to OP comment
I want to check this for every column in above query.
If I understand you correctly you want to update each column only if this column is empty. For this you need to run separate query for each column.
Sqlite has coalesce function that takes variable number of parameters and returns first not null.
UPDATE field UPDATE FieldTestDataTemp SET Image1 = coalesce(Image1, f10.image1)...
However - this not covers situation with empty fields so you need to carry about them (ex. set to null).
It's also good idea to use prepareStatement() / exec() instead of execSQL(). It allows to use placeholders instead of string concatenation.
You can do a single UPDATE and also check for null/empty:
UPDATE FieldTestDataTemp
SET Image1 = CASE WHEN Image1 IS NULL OR Image1 = ''
THEN f10.image1
ELSE Image1
END,
Image2 = CASE WHEN Image1 IS NULL OR Image2 = ''
THEN f10.image2
ELSE Image2,
...
But this will update every column in the UPDATE statement, even if the base 64 image string already be not null and not empty.
A possibly cleaner way to handle this would be to update each column separately. In this case, we can just add a WHERE clause to only update for empty/null image strings:
UPDATE FieldTestDataTemp
SET Image1 = f10.image1
WHERE COALESCE(Image1, '') <> ''
For my application, I need to query a sqlite database around 40-50 times. I am sure that the code I wrote is very inefficient. Unfortunately, I cannot find many examples online that involves querying the database many times.
String[] entryValArray = new String[indicesList.size()];
DBHelper dbHelper = new DBHelper(MainActivity.context);
SQLiteDatabase db = dbHelper.getReadableDatabase();
for (int i = 0; i < indicesList.size(); i++) {
int moddedIndex = Integer.parseInt(indicesList.get(i), 16) % DBHelper.numEntries;
String queryStr = "select * from " + DBHelper.TBL_NAME + " where " + DBHelper.IDStr +
" = " + Integer.toString(moddedIndex);
Cursor cursor = db.rawQuery(queryStr, null);
if (cursor.moveToFirst())
entryValArray[i] = cursor.getString(1);
cursor.close();
}
Basically, I am taking a list of strings, converting them to hex values, and then modding the value to get an index into a sqlite database. This is for a password generator application.
Is there a better way to do this, especially regarding creating a cursor and then closing it in every iteration.
First of all you have to change your query string as you need only one column value but you are using
Select *
instead of
Select yourColumn
. Secondly if your indices list size is not very large you can use
IN(values ) function of db instead of
" where " + DBHelper.IDStr +" = " + Integer.toString(moddedIndex);
this will return the result in only one query you don't have to run a whole loop.
Sorry, I'm new. I have a table and need to get the column ID of the first min value of the table. The table is organized so the values keep decreasing until they get to 0 and all subsequent values are equal to zero.
It is possible for none of the values to be zero in which case Id need the last ID. It is important that I only have one return ID because of how I'm implementing it. This is the code I tried first but I'm getting an error.
I did not try to add the exception of there being no 0s here because I thought it might be easier to add an If statement in the implementation of the method I use.
The error I get confuses me because It seems like I can't use FIRST when I thought I could, but here it is:
android.database.sqlite.SQLiteException: no such function: FIRST (code
1): , while compiling: SELECT FIRST (_id) FROM graph WHERE bac = 0;
My code:
public int getWhereZero(){
int zero = 0;
SQLiteDatabase db = getReadableDatabase();
String query = "SELECT FIRST (" + COLUMN_ID
+ ") FROM " + TABLE_GRAPH
+" WHERE " + COLUMN_BAC
+ " = 0;";
Cursor cursor = db.rawQuery(query, null);
if(cursor != null){
cursor.moveToFirst();
zero = cursor.getInt(cursor.getColumnIndex(COLUMN_ID));
cursor.close();
}
return zero;
}
SQLite doesn't have a FIRST() function. However, you can limit the number of rows returned to one using LIMIT, so sorting by the desired order will get the row you need:
SELECT column_id FROM graph ORDER BY bac LIMIT 1;
I made an application that generates random word from database. But there is a problem like that:
I insert some rows into the database and ID field is AUTOINCREMENT. I get a random word from database. But, when I delete a record and I insert the new one, as you know, the ID is skipping the old one.
So, when I try to get a random word, it may make an error occured. How can I solve this problem?
Thank you for your responds...
public void kelimeUret() {
SQLiteDatabase db = kelimeler.getReadableDatabase();
rastgele = new Random();
Cursor kayit = db.rawQuery("SELECT count(*) FROM kelimeler", null);
kayit.moveToFirst();
int max = Integer.parseInt(kayit.getString(0));
int min = 1;
int rastgeleKayit = rastgele.nextInt(max - min + 1) + min;
Cursor kayit2 = db.rawQuery("SELECT ingilizce FROM kelimeler WHERE id=" + rastgeleKayit, null);
kayit2.moveToFirst();
String sonuc = kayit2.getString(0);
olusturulanKelime = sonuc;
kelime = (TextView) findViewById(R.id.kelime);
kelime.setText(sonuc);
}
My code is here. Actually there is no problem. It works. But when random generates an ID that has been removed from database before, it gives error. I thought that I should generate an ordered numbers for records, but I couldn't find the way to do that. I want to do it in another way. (Not on ID)
Your easiest bet is probably to drop the AUTOINCREMENT if you can, and instead handle giving an ID by yourself.
Just query for the highest current ID and increment it yourself.