Sqlite Insert Runs Successfully But Does Have not any Effect On Database? - java

I am trying to add a single row to my table. It seems like it works just fine, but the row is not added to database. When i check the database there is no change on it.
I am trying to add it with insert method that SqliteDatabase provides with folowing code.
public void saveToCache(String word) {
ContentValues contentValues = new ContentValues();
contentValues.put("word", word);
long value = database.insert("CACHE",null, contentValues);
//The code below is for debug purposes, to see the if values are added
//But when executed it gives
//android.database.CursorIndexOutOfBoundsException: Index -1 requested,
//with a size of 13
Cursor cursor = database.rawQuery("SELECT * FROM CACHE",null);
for(int i=0; i< cursor.getCount();i++){
String a = cursor.getString(0); //This is where the exception above happens
}
}
The value attribute seems right, everytime I use the function, it increments by 1. But the rawQuery method below gives the error I have provided in the comment.
p.s : The table "CACHE" has only one COLUMN called word.

You need to change the loop that accesses the rows returned to the cursor:
Cursor cursor = database.rawQuery("SELECT * FROM CACHE",null);
while (cursor.moveToNext()) {
String a = cursor.getString(0);
// do something
}
After the call to rawQuery() the cursor's index is before the 1st row (if it exists).
The cursor does not advance to the first or to the next row without a call to moveToFirst() or moveToNext().

Related

Android SQLite insert method small clarification

i am learning some sqlite tutorial for android development and i try to understand this line of code:
1 ContentValues values = new ContentValues();
2 values.put(AppContract.HeadphoneEntry.COLUMN_NAME, "Toto");
3 values.put(AppContract.HeadphoneEntry.COLUMN_BREED, "Terrier");
4 values.put(AppContract.HeadphoneEntry.COLUMN_WEIGHT, 7);
5
6
7
8 long newRowId = db.insert(AppContract.HeadphoneEntry.TABLE_NAME, null, values);
Is this line of code (on line 8) inserting my values into the table ? or i am just storing the row id into the long type variable called "newRowId" ?
I ask because the data is inserted but i don't understand why ... because i thought that i am just storing the row id on that line.
Is this line of code (on line 8) inserting my values into the table ?
-> Yeah line 8 will insert your value into the table if db is initialized with SQLiteOpenHelper.getWritableDatabase() method.
or i am just storing the row id into the long type variable called "newRowId"?
-> When you insert with SQLiteDatabase.insert() it returns the row ID of the newly inserted row, or -1 if an error occurred.
The SQLiteDatabase insert method inserts a row and returns the rowid of the inserted row as a long or in the case of a conflict -1 to indicate that the row was not inserted. So the value of newRowId will either be a positive value greater than 0 if the row was inserted or -1 if not inserted and there was no other conflict (e.g. a Foreign Key constraint conflict will result in an exception being thrown).
conflicts could be a PRIMARY KEY, UNIQUE, CHECK or NULL constraint violation.
The insert method is a convenience method that generates the underlying SQL binding any parameters and executes that. The SQL generated will be something like:-
INSERT OR IGNORE INTO the_table_name (the_name_column, the_breed_column, the_weight_column) VALUES(?,?,?);
Where:-
the_table_name will be the value as per the first parameter i.e. whatever AppContract.HeadphoneEntry.TABLE_NAME resolves to.
the_name_column will be the value as per the first value of the first in ContentValues (i.e. the value that AppContract.HeadphoneEntry.COLUMN_NAME resolves to)
the_breed_column will be value as per the first value of the second ContentValues (i.e. the value that AppContract.HeadphoneEntry.COLUMN_BREED resolves to)
the_weight_column being the first value as per the third ContentValues (i.e. the value that AppContract.HeadphoneEntry.COLUMN_WEIGHT resolves to)
The ?'s are replaced by the 2nd values of the respective ContentValues (first from the first i.e. 'Toto', second from the second i.e. 'Terrier' ....) when the SQL statement is bound. Binding statements correctly encloses the actual values in single quotes and thus protects against SQL Injection.
After executing the sqlite3_last_insert_rowid() interface is invoked the result returned with 0 being converted to -1.
If you weren't to use the convenience method, then to replicate all that it does you would have to code something like :-
db.execSQL("INSERT OR IGNORE INTO " + AppContract.HeadphoneEntry.TABLE_NAME +
"(" +
AppContract.HeadphoneEntry.COLUMN_NAME +
"," + AppContract.HeadphoneEntry.COLUMN_BREED +
"," + AppContract.HeadphoneEntry.COLUMN_WEIGHT +
") " +
"VALUES(?,?,?)",
new String[]
{
"Toto",
"Terrier",
"7"
}
);
Cursor csr = db.rawQuery("SELECT last_insert_rowid()",null);
newRowID = -1;
if (csr.moveToFirst()) {
newRowID = csr.getLong(0);
if (newRowID <= 0) {
newRowID = -1;
}
}
csr.close();
where db is an instantiated SQLiteDatabase object.
If your goal is to try to predict the next rowid to be used, then you could use :-
Cursor csr = db.rawQuery("SELECT max(rowid)+1 FROM " + AppContract.HeadphoneEntry.TABLE_NAME + ";",null);
long newRowID = 1; //
if (csr.moveToFirst()) {
newRowID = csr.getLong(0);
}
BUT BEWARE SQLite does not guarantee that the next inserted row will be 1 greater than the highest existing rowid. If you use AUTO INCREMENT then the sqlite_sequence table stores the highest used rowid for the table and the higher of that and the max(rowid) value will be used. Even then their is still no guarantee that the predicted value will be the value used. It is far better to not try to predict the value of the rowid but to retrieve it and thus for Android Java to use the convenience method.
An exception is if you delve into utilising negative rowid values when -1 may then not indicate no insertion.

Cursor isAfterLast() returns true when reaching last row

I wanted to iterate over a cursor over a table with 2 rows of data. My first try was:
c.moveToFirst();
while(!c.isAfterLast()){
//this code runs once
c.moveToNext();
}
However after debugging I noticed that I am missing the last row of my data. And that was because the while loop ends when the mPos variable becomes equal to mCount in the counter. After replacing the above code with the one below the problem was solved:
c.moveToFirst();
do{
//this code runs twice
}while(c.moveToNext())
Essentially in the first method, the while loop runs 1 time less than the second one. Isn't isAfterLast supposed to return true only after the cursor passes the last row?
Note that moveToNext() returns a boolean signifying that there is a next (true), but ALSO, if true - it moves the cursor. So that in this case when you return to evaluate while(!c.isAfterLast()) after c.moveToNext(); you are already at the last item (and so the cursor is pointing to the position after the last row.
If your goal is to iterate through the cursor, then you can just do this:
while (c.moveToNext()) {
//do whatever with your data - like
//String value = c.getString(c.getColumnIndex("SOME_COLUMN_NAME"));
}
You can look at the related discussion here.

Returning a single column value from SQL database

I need to get the latest entry from my database, but not the autoincrement.
This function is in my databasehandler:
public int getLatestRouteNumber()
{
int number = 0;
SQLiteDatabase db = this.getReadableDatabase();
String query = "SELECT MAX("+ KEY_ROUTENUMBER + ") FROM " + TABLE_LOCATIONS;
Cursor c = db.rawQuery(query, null);
if (c.moveToFirst() && c != null) {
number = c.getInt(3);
}
return number;
}
it craches at the line where "number = c.getInt(3).
The third column in my database exists and has data in it.
The error I'm gettin is "Couldn't read row 0, col 3 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it." I only need one value in the entire database, not even an entire row.
You have only one column in cursor but trying to get value of 3rd column... Tat is the error
Change it to getInt(0);
The returned result-set has nothing to do with table columns in your case. You should use
number = c.getInt(0);
Your resultset contains just one column and one row, basically a scalar value, it doesn't matter how many columns you have in your table, what you should consider here is the value you obtain from your query In your case just one value. Use
getInt(0)
have you tried something like this :
String query = "SELECT MAX("+ KEY_ROUTENUMBER + ") as my_max FROM " + TABLE_LOCATIONS;
And :
columnIndex = c.getColumnIndexOrThrow("my_max");
number = c.getInt(columnIndex );
That's better than using indexes, indexes may be wrong if the raw query changes.
getInt (3) returns the value of the 3rd column returned by the query. Your query only had 1 column.
Change getInt (3) to getInt (0)
"c.getInt(3);" does not get the value from the column in your table, it gets it from the column in your cursor.
And you only selected one column into your cursor.
So I believe it should be "c.getInt(1);"

Grabbing a value from SQLite database using a cursor and converting to int

This may not be the best approach to grabbing a value from a column in a database but here's what I have so far:
I have a table called switches with a column called levels. The column levels is an integer value column. I want to grab the integer values from the levels column. How can I do that? I tried this but I am unable to just get the integer value vs. getting the Cursor.
Here's my code:
SQLiteDatabase sqLiteDatabase;
sqLiteDatabase = dbHandler.getReadableDatabase();
sqLiteDatabase.beginTransaction();
Cursor cursor;
Integer level;
String select_level = "SELECT level FROM switches";
cursor = sqLiteDatabase.rawQuery(select_level, null);
level = Integer.parseInt(cursor.toString());
The problem is Cursor is not an integer, so I thought to convert to string then int but it seems like I get a number format exception. I think it's because the cursor is giving me the column name and the integer value.
How do I just grab the integer value for a specific column using raw SQL with SQLite database?
After this line of code,
cursor = sqLiteDatabase.rawQuery(select_level, null);
Add the below code
while (cursor.moveToNext()) {
level = cursor.getInt(0);
}

I store the score by hole of a round of golf in a database. I want to write a function that sums that column in the table and displays in a toast

This is the function that I have created. The Playgolf table has columns id, holepar, strokes, putts. I'm looking to sum up the strokes.
I have edited the code to this and now I'm getting this error...any ideas?
public void DisplaySum(int sum)
{
//Setup a local variable to store sum
int intRoundsSUM = 0;
db.open();
//Setup your database cursor
Cursor c = db.getPLAYGOLF();
Toast.makeText(getBaseContext(), intRoundsSUM, Toast.LENGTH_LONG).show();
//Iterate through the cursor
//Sum up each value
c.moveToFirst();
while(c.isAfterLast() == false) {
intRoundsSUM += c.getInt(2);
c.moveToNext();
}
Toast.makeText(getBaseContext(), intRoundsSUM, Toast.LENGTH_LONG).show();
}
// LOG CAT MAIN ERROR:
//E/AndroidRuntime(597): android.content.res.Resources$NotFoundException: String resource ID #0xa
You have to manage your cursor, start with
cursor.moveToFirst();
while(cursor.isAfterLast() == false) {
intRoundsSUM += c.getInt(2);
cursor.moveToNext();
}
Also read about letting your activity control the life cycle of the cursor with activity.startManagingCursor(cursor);
You can iterate over the cursor rows with the next cycle:
while (cursor.moveToNext()) {
intRoundsSUM += c.getInt(2);
}
But you can also try to make 'sum' selection from the database. Something like this:
SELECT SUM(strokes_column) FROM golf_table
It will return table with one column and one row that stores the necessary sum.
Try c.moveToFirst() before intRoundsSUM += c.getInt(2); to fix the error.
To sum them all you can use while (c.moveToNext()) or make a sum in your sql query (which would be better). See http://www.w3schools.com/sql/sql_func_sum.asp
There might be two reasons:
Playgolf table is empty. check the size by using c.getCount();
You are at the end of the cursor. use c.moveToFirst() to go to the beginning of the cursor.

Categories