This is my code:
public int getIdMotChuDe(String tenChuDe) {
int IDChuDe = 0;
try
{
Cursor c = null;
c = database.rawQuery(
"SELECT ChuDeID FROM DanhSachChuDe WHERE TenChuDe = ?"
, new String[] {tenChuDe});
c.moveToFirst();
IDChuDe = c.getInt(c.getColumnIndex("ChuDeID"));
c.close();
}
catch(Exception e)
{
e.printStackTrace();
}
return IDChuDe;
}
I'm trying to get ChuDeID from DanhSachChuDe table with condition in WHERE clause. But i don't know why this function always return 0.
Help me please. Thanks! Sorry because my english.
This could be because an Exception is being thrown. The code you are using is not correctly checking the state of your Cursor - it attempts to moveToFirst() before any checking too see if the object is not null.
Your code also assumes a result is always returned. This is bad practise, and should be avoided. A much safer and more common solution is the following:
if (cursor != null) {
// If the cursor has results, move the cursor to first row
if (cursor.moveToFirst()) {
do {
// YOUR METHODS HERE
// then move to next row
} while (cursor.moveToNext());
}
}
Related
The issue is purely with the contents inside the tables. If the table is not empty (with one or more records), application works perfectly. I am deleting the contents of table and immediately after that reading the same table, it throws exception and app force closes.
I tried searching for it but couldn't conclude. The key point is : index out of bound exception which is thrown at movetofirst() method of cursor when i am going to read the table, i suppose... Please help.
public List<TableData> readForPaymentDetais()
{
List<TableData> paymentDetails = new ArrayList<TableData>();
try
{
String selectQuery = "select * from PaymentDetails";
SQLiteDatabase database = this.getWritableDatabase();
Cursor cursor = database.rawQuery(selectQuery, null);
if(cursor.getCount() !=0)
{
if(cursor.moveToFirst())
{
do
{
TableData data = new TableData();
data.setPaymentMade(Float.valueOf(cursor.getString(0).toString()));
data.setDateOfPayment(cursor.getString(1));
paymentDetails.add(data);
}
while(cursor.moveToNext());
}
}
return paymentDetails;
}
catch(Exception exc)
{
return null;
}
}
Before executing moveToFirst method of cursor please check whether cursor is empty. For that you can use code like:
if (mCursor.getCount() == 0) {
// cursor is empty
}
If cursor is not empty put your stuff in else part.
I have been working to solve this pity problem for hours now. I have used a lot other cursor methods in my app which are working as a charm but this one has been a real difficult to solve.
public int getCategoryCode(String category){
int d=0;
Cursor cg=database.query("categoryTable", null, "category_name='"+category+"'", null, null, null, null);
cg.moveToFirst();
Log.d("success", String.valueOf(cg.getColumnIndex("_id")));
Log.d("success", String.valueOf(cg.getCount()));
cg.getInt(cg.getColumnIndex("_id"));
return d;
The program return an exception when i try to retrieve the 'integers' saved in the column "_id". I have checked that there are results present in the "id" column because cg.getColumnIndex() return 0 in the logcat. Please help!!
Try this (EDITED)!!:
public int getCategoryCode(String category){
int d=0;
Cursor cg= database.rawQuery("SELECT _id FROM categoryTable WHERE category_name = '"+category+"' ",null);
if(cg.moveToFirst()){
if(!mCursorActual.isNull(cg.getColumnIndex("_id"))){
d = cg.getInt(cg.getColumnIndex("_id"));
} else {
d = 0;
}
cg.close();
return d;
}
}
Try to check:
if((cg!= null) && (cg.getCount() > 0)){
cg.moveToFirst();
//DO YOUR STUFF
}
Use the following code,
cursor.moveToFirst();
if(cursor.isAfterLast() == false) {
// Your logic goes here
}
Also you can be sure that there is data in your table, use a breakpoint to make sure your query is right, see if the cursor object once the query is complete.
I am new to Android programming and am trying to understand the best practices.
I want to do multiple inserts into two different database tables, but as one transaction (as the tables shared a foreign key). I want my function to return a result so that I can display a Toast or something to say that an error occurred, otherwise I want to return the row ID of the first insert.
I believe one way of doing this is sort-of as follows (Disclaimer: psuedo-ish code, probably won't compile!):
Long result = -1;
myDatabase.beginTransaction();
try {
// Insert into first table
ContentValue someValues = new ContentValues();
someValues.put("dbfield1", 1);
result = myDatabase.insert(DATABASE_TABLE_1, null, someValues);
if (-1 != result ) {
// Insert into second table
someValues.clear();
someValues.put("dbfield2", 2);
if( myDatabase.insert(DATABASE_TABLE_2, null, someValues) < 0 ) {
result = -1;
}
}
mDatabase.setTransactionSuccessful();
} catch(Exception e) {
// An error occurred
result = -1;
} finally {
mDatabase.endTransaction();
}
Is there a simpler/better way of doing this?
You can override bulkInsert inside your ContentProvider
your Code looks fine. The Method should return the inserted Rows Value but you can customize that so you return only the first ID.
public int bulkInsert(Uri uri, ContentValues[] values) {
Log.e("BULK", "Bulk insert started for URI" + uri.toString());
bulkSqlDB = database.getWritableDatabase();
int numInserted;
bulkSqlDB.beginTransaction();
try {
for (ContentValues cv : values) {
insert(uri, cv);
}
bulkSqlDB.setTransactionSuccessful();
numInserted = values.length;
} finally {
getContext().getContentResolver().notifyChange(uri, null);
bulkSqlDB.endTransaction();
}
return numInserted;
}
How can I get the number of rows updated using an update statement in SQLite in Android?
Note that I need to use some type of raw execute of a SQL statement, rather than do anything with ContentValues because I need a dynamic query. Thus I can't make use of the SQLiteDatabase.update() method. For example, I'm running something like
UPDATE my_table
SET field_name = field_name + 1
The methods I know of return void, e.g. SQLiteDatabase.execSQL(). SQLiteDatabase.rawQuery() returns a Cursor, but the cursor has zero rows and its count is always -1.
You could do your insert whichever way you want, and then do a select and use the changes() function to return the number of affected rows.
To expand on Mat's answer, here's the example code for getting the updated row count:
Cursor cursor = null;
try
{
cursor = db.rawQuery("SELECT changes() AS affected_row_count", null);
if(cursor != null && cursor.getCount() > 0 && cursor.moveToFirst())
{
final long affectedRowCount = cursor.getLong(cursor.getColumnIndex("affected_row_count"));
Log.d("LOG", "affectedRowCount = " + affectedRowCount);
}
else
{
// Some error occurred?
}
}
catch(SQLException e)
{
// Handle exception here.
}
finally
{
if(cursor != null)
{
cursor.close();
}
}
Expanding on Mat and Pang's answers...
Could we skip the Cursor and use simpleQueryForLong()?
e.g.
public long getChangesCount() {
SQLiteDatabase db = getReadableDatabase();
SQLiteStatement statement = db.compileStatement("SELECT changes()");
return statement.simpleQueryForLong();
}
You can use SQLiteStatement.executeUpdateDelete method for this:
SQLiteDatabase db = getReadableDatabase();
SQLiteStatement statement = db.compileStatement("[your sql here]");
int affectedRows = statement.executeUpdateDelete();
The same method used internally in SQLiteDatabase.update(...) methods.
Which of the following two should I be using to make sure that all the cursors are closed?
Cursor c = getCursor();
if(c!=null && c.getCount()>0){
try{
// read values from cursor
}catch(..){}
finally{
c.close();
}
}//end if
OR
Cursor c = getCursor();
try{
if(c!=null && c.getCount()>0){
// read values from cursor
}//end if
}catch(..){
}finally{
c.close();
}
Please advise.
Neither, but the second one was closest.
Option 1 doesn't properly close the
Cursor when getCount() == 0
Option 2 leaves the finally block exposed to a null pointer exception
I would use:
Cursor c = getCursor();
try {
if(c!=null && c.getCount()>0){
// do stuff with the cursor
}
}
catch(..) {
//Handle ex
}
finally {
if(c != null) {
c.close();
}
}
... or if you expect the cursor to be null frequently, you could turn it on its head a little bit:
Cursor c = getCursor();
if(c != null) {
try {
if(c.getCount()>0) {
// do stuff with the cursor
}
}
catch(..) {
//Handle ex
}
finally {
c.close();
}
}
This is even better:
does not use c.getCount() - counting might require extra work for the database and is not needed
initialize the cursor before the query block, so failure to create the query is not followed by the finally block
The code:
Cursor c = query(....);
if (c != null) {
try {
while (c.moveToNext()) { // If empty or after last record it returns false.
// process row...
}
}
finally {
c.close();
}
}
Note that c might be null in case of error or empty cursor. See https://stackoverflow.com/a/16108435/952135. I would report null return value in case of empty cursor as a bug, though.
Best practice is the one below:
Cursor c = null;
try {
c = query(....);
while (c.moveToNext()) { // If empty or next to last record it returns false.
// do stuff..
}
} finally {
if (c != null && !c.isClosed()) { // If cursor is empty even though should close it.
c.close();
c = null; // high chances of quick memory release.
}
Depends on what you're catching, but I'd say the second one, just in case c.getCount() throws an exception.
Also, some indentation wouldn't go amiss :)
I'd say the first one, mainly because the second one will try to call c.close() even if c is null. Also, according to the docs, getCount()doesn't throw any exceptions, so there's no need to include it in the try block.
I think my answer is the best one :
Cursor cursor = null;
try {
cursor = rsd.rawQuery(querySql, null);
if (cursor.moveToFirst()) {
do {
// select your need data from database
} while (cursor.moveToNext());
}
} finally {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
cursor = null;
}
}
I think #skylarsutton's is a right answer for the question. However, I want to leave codes for the question (any codes in answers seems to have some flaws). Please consider to use my code.
Cursor c = query(....);
if (c != null) {
try {
//You have to use moveToFirst(). There is no quarantee that a cursor is located at the beginning.
for(c.moveToFirst();!c.isAfterLast();c.moveToNext()) {
// process row...
}
}
finally {
c.close();
}
}