I try to get an Item out of my SQL db in android, everything goes well, the only thing I am struggling with is to get the INTEGER value is there is nothing filled in in the DB (null?)
So I first initialize it, then get the Integer value out of the DB and then assign it to an instance of my class. I was once told that if it will get nothing out of the DB it will keep the initialized value, but this might be wrong? I use now:
int score = 100;
score = c.getInt(11);
q.setScore(score);
I was once told that if it will get nothing out of the DB it will keep the initialized value
That is true for Embedded SQL. You seem to be using a resultset object, so it is not true.
Resultset objects typically return 0 if you try to get a numeric null value from a column.
Use c.wasNull() to check if the value you just read was null and not 0.
EDIT (added the code from Jack's comment):
int score;
if (c.isNull(11)) {
score = 100;
} else {
score = c.getInt(11);
}
q.setScore(score);
http://developer.android.com/reference/android/database/Cursor.html#getInt(int)
*public abstract int getInt (int columnIndex) Since: API Level 1 Returns the value of the requested column as an int. The result and
whether this method throws an exception when the column value is null,
the column type is not an integral type, or the integer value is
outside the range [Integer.MIN_VALUE, Integer.MAX_VALUE] is
implementation-defined. Parameters columnIndex the zero-based index of
the target column. Returns the value of that column as an int.*
Related
I have an issue that may in fact be a design issue but I am struggling to find a way around it.
In my sqlite database in my android application, I have a table called Customer. This has around 40 columns of various string and int data types. In practice, any of these columns may or may not be null.
In my code, I have a function simply called getCustomer(), which queries the database for a specific customer, and places all their cells from the database into a Customer class, which contains variables for each column. I can then pass that customer object around as I wish. The getCustomer() function returns this Customer object.
My problem is integers which may be null. I am familiar with how int cannot be null in java, but how Integer can be null. But my problem actually lies in the fact that the cells in the database can be empty (eg null).
For string columns, I simply do this:
Customer cust = new Customer();
cust.firstName = cursor.getString(0);
If cursor.getString(0); returns a null value, then the firstName variable is assigned null. Nice and simple. However with an int:
Customer cust = new Customer();
cust.daysSinceJoining = cursor.getInt(5);
The above crashes at run-time if daysSinceJoining is null. So I tried the following:
Customer cust = new Customer();
if (cursor.getInt(5) != null)
cust.daysSinceJoining = cursor.getInt(5);
However this gives me a compiler error, as you cannot use an int in a null comparison like that.
How can I get around this problem? How can I retrieve an int from an sqlite database when the int value could be null?
#sanders is right about the isNull() method and here's how you edit your code to use it:
Customer cust = new Customer();
if (!cursor.isNull(5))
cust.daysSinceJoining = cursor.getInt(5);
You could try the isNull() function.
Please take a look to that answer:
getInt null-constraints
I think that should work for you:
int lIndex = cursor.getColumnIndexOrThrow(COLUMN);
Integer lInteger = null;
if (!cursor.isNull(lIndex)
lInteger = cursor.getInt(lIndex);
You can create a cursor wrapper and add new functionality to the cursor class:
public class CustomCursor extends CursorWrapper {
public CustomCursor(Cursor cursor) { super(cursor); } //simple constructor
public Integer getInteger(int columnIndex) { // new method to return Integer instead of int
if (super.isNull(columnIndex)){
return null;
}else{
return super.getInt(columnIndex);
}
}
}
Example usage:
Cursor defaultCursor = db.rawQuery("select null,2 ", null);
defaultCursor.moveToFirst();
CustomCursor customCursor = new CustomCursor(defaultCursor);
customCursor.moveToFirst(); //custom cursor can do anything that default cursor can do
int defaultInt0 = defaultCursor.getInt(0); //nulls are usually converted into zero
int defaultInt1 = defaultCursor.getInt(1); //2 is correct
int customInt0 = customCursor.getInt(0); //these 2 are same as above , ie zero and 2
int customInt1 = customCursor.getInt(1);
Integer customInteger0 = customCursor.getInteger(0); // this will give a null Integer
Integer customInteger1 = customCursor.getInteger(1); // this will give a 2 Integer
Log.v("custom log.v call ", "lets see what outputs, null is usually converted to the word 'null' by the String.valueOf method :"
+String.valueOf(defaultInt0)+","+String.valueOf(defaultInt1)+","
+String.valueOf(customInt0)+","+String.valueOf(customInt1)+","
+String.valueOf(customInteger0)+","+String.valueOf(customInteger1)
);
//V: lets see what outputs, null is usually converted to the word 'null' by the String.valueOf method :0,2,0,2,null,2
if (cursor.getInt(5) !=0){
cust.daysSinceJoining = cursor.getInt(5);
}
or
int index = cursor.getColumnIndex(KEY_NAME);
Integer x = null;
if (!cursor.isNull(index)
cust.daysSinceJoining = cursor.getInt(5);
}
see the documentation
getInt() documentation:
Iam trying to find average of a column in my sqlite database.
Here is the code:
public void getAvgMileage(Prediction pd)
{
String [] columns = new String[]{KEY_ROW_ID, KEY_KM, KEY_FUEL_QTY, KEY_FUEL_PRICE, KEY_TOTAL_COST, KEY_MILEAGE, KEY_DATE,KEY_TANK_FULL};
predictionCursor = ourDatabase.rawQuery("SELECT AVG(_mileage) FROM fuel_table WHERE _mileage IS NOT NULL ORDER BY _id DESC LIMIT 5", null);
predictionCursor.moveToFirst();
if(predictionCursor!=null && predictionCursor.getCount()>0)
{
predictionCursor.moveToLast();
findAvgMileage = (Double.valueOf(predictionCursor.toString()));
pd.setpredictionMileage(findAvgMileage);
}
}
But Iam geting a NullPointerException.
Any help??
Thank you.
It doesn't look like you are getting the value out of the cursor for your SQL recordset
This line:
findAvgMileage = (Double.valueOf(predictionCursor.toString()));
looks like it's trying to take a double value of the tostring() of the actual cursor - which I don't think is going to usable or at least not parseable to Double. The return of Cursor.toString() may well be a null value.
replace the line with the following:
findAvgMileage = predictionCursor.getDouble(0);
This new line will fetch out the value in the first column of the current position of the curosr which in your SQL should be the average value you want.
I created database table in my android app. I used this query:
CREATE TABLE foo (_id INTEGER PRIMARY KEY AUTOINCREMENT, mybool BOOLEAN)
Than I added row to the table, that the value of mybool will be true.
I ran the sqlite3 command to see the value in the table, and I saw:
_id | mybool
----------------------
1 | 1
That is corret, the true value became to 1.
The strange thing is in the reading. I read the table like that:
ContentValues values = new ContentValues();
Cursor cursor = db.rawQuery("SELECT * FROM foo", null);
DatabaseUtils.cursorRowToContentValues(cursor, values);
Then I get strange result:
values.getAsBoolean("mybool"); // return false - WRONG
values.getAsInteger("mybool"); // return 1 = true - CORRECT
I use the code like that to get boolean value:
values.getAsInteger("mybool") != 0;
But it's strange.
Why I get always false in the getAsBoolean function? Is there any bug in the ContentValues class? Anyone else having this problem?
DatabaseUtils.cursorRowToContentValues() stores everything as strings (except blobs). ContentValues.getAsBoolean() will attempt to convert the string to a boolean (using Boolean.valueOf()), but that only works if the string is equal to "true", not "1".
This looks like an Android bug to me.
You've skipped some code here.
What's your proof that values.getAsBoolean("mybool") returns false? You have to return a Boolean. How are you checking it?
ContentValues.getAs returns a value if the key can be found, or null if it can't or if the value can't be converted. Be sure that you're doing a full test.
getAsBoolean does not return a boolean but a Boolean wrapper object, which can be either null, Boolean.FALSE, or Boolean.TRUE.
If you can ensure that there aren't NULLs, use values.getAsBoolean("mybool").booleanValue() to get the actual value.
I don't know if it's the best solution for this problem, but this code below works for me:
Integer result = contentValues.getAsInteger(attributeName);
if(result == null || result == 0) {
parameter = false;
} else {
parameter = true;
}
Get boolean result like below:
boolean result = values.getAsInteger("mybool") == 1;
Hi This my second question here.
I have the following table
|-----|-------|------|------|
|._id.|..INFO.|.DONE.|.LAST.|
|..1..|...A...|...N..|......|
|..2..|...B...|...Y..|..L...|<--- cursor.moveToPosition((int)_id-1);
|..3..|...C...|...Y..|......|
|..4..|...D...|...Y..|......|
|..5..|...E...|...N..|......|
|..6..|...F...|...N..|......|
|-----|-------|------|------|
I use the code:
cursor = db.query(TABLE_NAME, new String[]{INFO,DONE,LAST},null,null,null,null,null);
cursor.moveToPosition((int)_id-1);
String Yval = cursor.getString(cursor.getColumnIndex(DONE));
do
{
cursor.moveToNext();
Yval= cursor.getString(cursor.getColumnIndex(DONE));
}
while (Yval=="Y");
s = Yval;
I initially point the cursor to the LAST row I accessed, then I make a loop to go through the values in the DONE column, not stopping if there are Y's in the row of the column. When an N appears in the loop, the loop should stop.
But it doesn't work.
Yval never equals "Y". So the cursor does one 'moveToNext' and then exits the loop, because it doesn't read Yval as a "Y".
(I also changed everything to integers. 1 for N, and 0 for Y, but it still didn't work)
So what am I doing wrong here?
So you have to use equals() method if you want to compare Strings
while (Yval.equals("Y"));
You should know that:
== tests for reference equality.
equals tests for value equality.
So you want to test if Yval String has Y value so you have to use equals() method.
You approach doesn't work bacause:
String data = "lorem";
data == "lorem" ==> FALSE
data.equals("lorem") == TRUE
Also make sure that your Cursor has valid row so you need to add to condition also cursor.moveToNext() so
cursor.moveToNext() && (Yval.equals("Y")
also you need to treat cursor.moveToPosition((int)_id-1) so add it to condition.
I recommend changing a few things:
if(cursor.moveToPosition((int) _id - 1)) {
int doneIndex = cursor.getColumnIndex(DONE);
String Yval;
do {
Yval = cursor.getString(doneIndex);
} while(Yval.equals("Y") && cursor.moveToNext());
}
You should check if a row exists at position _id - 1 since the SQLite _id is a unique id, not the position of a row in a Cursor.
You only need to fetch the index of the DONE column once, simply store it in a local variable.
As deceiver mentioned, String are tested with equals() and similar methods.
You need consider what happens if all of the rows are "DONE", then you must stop trying to read the Cursor before an out of bounds exception is thrown.
I have a database that contains decimals. The column is set up as ".. decimal(5,2) not null. What I'm trying to do is to find the sum of the column and displaying it in a text field by using this code..
public int getTotal() {
Cursor cursor = sqliteDatabase2.rawQuery(
"SELECT SUM(thedata) FROM thetable", null);
if(cursor.moveToFirst()) {
return cursor.getInt(0);
}
return cursor.getInt(0);
}
However, when returned the value is a whole number. It should be something like 20.75 instead of just 20.
I'm not very familiar with SQLite, so please help.
On top of Xperimental's answer, you are calling getInt() on the Cursor, and you are returning and int from getTotal(). Here, int is shorthand for integer, what you refer to as a "whole number". If you want floating-point values, use getFloat() and return a float or Float.
SQLite doesn't know the datatype DECIMAL, so it could be possible, that it defaults back to the INTEGER datatype it knows. Try to use another datatype, which is recognized by SQLite. The datatypes SQLite knows can be found on the following page:
http://www.sqlite.org/datatype3.html