androidandroid-sqlitedelete-rowmobile-application

My mobile application crashes when deleting item


I am trying to develop a mobile application to get familiar with SQLite database. In here create, add methods are working. But when I am going to delete in list view the mobile app crashes. Here is the code that I have written.

In MainActivity.java

        lv_customerList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                CustomerModel clickedCustomer = (CustomerModel) parent.getItemAtPosition(position);
                dataBaseHelper.deleteOne(clickedCustomer);
                extracted(dataBaseHelper);
                Toast.makeText(MainActivity.this, "Deleted" ,Toast.LENGTH_SHORT).show();
            }
        });



    }

    private void extracted(DataBaseHelper dataBaseHelper) {
        customerArrayAdapter = new ArrayAdapter<CustomerModel>(MainActivity.this, android.R.layout.simple_list_item_1, dataBaseHelper.getEveryone());
        lv_customerList.setAdapter(customerArrayAdapter);
    }


}

In databaseHelper.java class

`

public boolean deleteOne(CustomerModel customerModel){

        SQLiteDatabase db = this.getWritableDatabase();
        String queryString = "DELETE FROM" + CUSTOMER_TABLE + " WHERE " + COLUMN_ID + " = " + customerModel.getId();

        Cursor cursor = db.rawQuery(queryString, null);

        if(cursor.moveToFirst()){
            return true;
        }else {
            return false;
        }
    }

Solution

  • You have omitted a space between the keyword FROM and the table name and thus will encounter an exception along the lines of:-

     android.database.sqlite.SQLiteException: near "FROMcustomer": syntax error (code 1 SQLITE_ERROR): , while compiling: DELETE FROMcustomer WHERE _id = 9999
    

    HOWEVER, you would then ALWAYS encounter a returned result of false from the DeleteOne method (see Demo below).

    This is due to a two-fold issue a) that the rawQuery method should ONLY be used for returning data that is extracted as an output SQL statement i.e. a SELECT statement or some PRAGMA statements and b) that other statements such as DELETE do not return anything and actually result in a rollback undoing what they have done.

    Instead you should either use:-

    1. an execSQL method, which again does not return a result,

      1. exeSQL does what is to be done, which may be nothing, or it fails, or
    2. the respective convenience method, e.g. the delete method for a deletion.

      1. the convenience methods, in addition to undertaking the action, do return an appropriate result:-

        1. the insert method returns the rowid or alias thereof for ROWID tables
        2. the delete and update methods return the number of affected rows (number of rows delete or updated).
      2. i.e. the convenience methods invoke the appropriate SQLite API function AFTER the execution to return the value

    Demo

    The following is a demonstration of:-

    1. a working (at least not failing) version of your DeleteOne method, and
    2. an example of using the execSQL method and then returning a useful result, and
    3. the suggested use of the delete convenience method

    The following is the DatabaseHelper class used for the Demo that is based upon what can be ascertained from your code:-

    class DatabaseHelper extends SQLiteOpenHelper {
        public static final String DATABASE_NAME = "the_database";
        public static final int DATABASE_VERSION = 1;
    
        public static final String CUSTOMER_TABLE = "customer";
        public static final String COLUMN_ID = BaseColumns._ID;
        public static final String COLUMN_WHATEVER = "_whatever";
    
        private DatabaseHelper(Context context) {
            super(context,DATABASE_NAME,null,DATABASE_VERSION);
        }
    
        private static volatile  DatabaseHelper instance;
        public static DatabaseHelper getInstance(Context context) {
            if (instance==null) {
                instance = new DatabaseHelper(context);
            }
            return instance;
        }
    
        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(
                    "CREATE TABLE IF NOT EXISTS " + CUSTOMER_TABLE +"(" +
                    COLUMN_ID + " INTEGER PRIMARY KEY" +
                    "," + COLUMN_WHATEVER + " TEXT" +
                    ");"
            );
        }
    
        @Override
        public void onUpgrade(SQLiteDatabase db, int i, int i1) {
    
        }
    
        public boolean deleteOne(/*CustomerModel customerModel*/ long id){
            SQLiteDatabase db = this.getWritableDatabase();
            String queryString = "DELETE FROM " + CUSTOMER_TABLE + " WHERE " + COLUMN_ID + " = " + /*customerModel.getId()*/ + id;
            Cursor cursor = db.rawQuery(queryString, null);
            if(cursor.moveToFirst()){
                return true;
            }else {
                return false;
            }
        }
    
        /* Using EXECSQL to return result */
        public long DeleteByExecSQL(long id) {
            SQLiteDatabase db = this.getWritableDatabase();
            long beforeDeletionCount, afterDeletionCount;
    
            db.beginTransaction();
            beforeDeletionCount = getTableRowCount(CUSTOMER_TABLE,db);
            db.execSQL("DELETE FROM " + CUSTOMER_TABLE + " WHERE " + COLUMN_ID + "=?",new String[]{String.valueOf(id)});
            afterDeletionCount = getTableRowCount(CUSTOMER_TABLE,db);
            db.setTransactionSuccessful();
            db.endTransaction();
            return beforeDeletionCount - afterDeletionCount;
        }
    
        /* Using Convenience DELETE */
        public long DeleteViaConvenienceMethod(long id) {
            SQLiteDatabase db = this.getWritableDatabase();
            return db.delete(CUSTOMER_TABLE,COLUMN_ID+"=?",new String[]{String.valueOf(id)});
        }
    
        /* method to get the number of rows in the table */
        public long getTableRowCount(String table, SQLiteDatabase db) {
            long rv=0;
            if (db == null) {
                db = this.getWritableDatabase();
            }
            Cursor csr = db.query(table,new String[]{"count(*)"},null,null,null,null,null);
            if (csr.moveToFirst()) rv = csr.getLong(0);
            csr.close();
            return rv;
        }
    
        /* Insert using the convenience INSERT method (returns rowid or alias thereof of inserted row) */
        public long insertCustomer(Long id, String whatever) {
            ContentValues cv = new ContentValues();
            if (id!=null) cv.put(COLUMN_ID,id);
            cv.put(COLUMN_WHATEVER,whatever);
            return this.getWritableDatabase().insert(CUSTOMER_TABLE,null,cv);
        }
       /* for generated id */
        public long insertCustomer(String whatever) {
            return insertCustomer(null,whatever);
        }
    }
    

    To actually demonstrate the 3 approaches, the following Activity code:-

    public class MainActivity extends AppCompatActivity {
    
        DatabaseHelper dbh;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            dbh = DatabaseHelper.getInstance(this);
    
    
            dbh.insertCustomer("C1");
            dbh.insertCustomer("C2");
            dbh.insertCustomer(100L,"C3");
            dbh.insertCustomer("C4");
            dbh.insertCustomer("C5");
    
            try {
                Log.d("DBINFO_DLT1_1","DELETED=" + dbh.deleteOne(9999));
                Log.d("DBINFO_DLTE_1","DELETED=" + dbh.deleteByExecSQL(9999));
                Log.d("DBINFO_DLTC_1","DELETED=" + dbh.deleteViaConvenienceMethod(9999));
    
                Log.d("DBINFO_DLT1_2","DELETED="+dbh.deleteOne(100));
                dbh.insertCustomer(100L,"C3");
                Log.d("DBINFO_DLTE_2","DELETED=" + dbh.deleteByExecSQL(100));
                dbh.insertCustomer(100L,"C3");
                Log.d("DBINFO_DLTC_2","DELETED=" + dbh.deleteViaConvenienceMethod(100));
            } catch (SQLiteException e) {
                e.printStackTrace();
            }
        }
    }
    

    When run then the results are:-

    2023-11-19 12:20:27.995 D/DBINFO_DLT1_1: DELETED=false
    2023-11-19 12:20:27.997 D/DBINFO_DLTE_1: DELETED=0
    2023-11-19 12:20:27.997 D/DBINFO_DLTC_1: DELETED=0
    
    
    2023-11-19 12:20:27.998 D/DBINFO_DLT1_2: DELETED=false
    2023-11-19 12:20:28.000 D/DBINFO_DLTE_2: DELETED=1
    2023-11-19 12:20:28.001 D/DBINFO_DLTC_2: DELETED=1
    

    It is suggested that you refer to https://developer.android.com/studio/debug, this would have enabled you to ascertain the initial issue.