我正在尝试开发一个移动应用程序来熟悉SQLite数据库。在这里创建,添加方法正在工作。但是当我要在列表视图中删除时,移动应用程序崩溃了。这是我写的代码。
在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);
}
}
在databaseHelper.java类中
`
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;
}
}
您省略了关键字
FROM
和表名称之间的空格,因此将遇到以下异常:-
android.database.sqlite.SQLiteException: near "FROMcustomer": syntax error (code 1 SQLITE_ERROR): , while compiling: DELETE FROMcustomer WHERE _id = 9999
但是,您总是会遇到从 DeleteOne
方法返回的结果
false(参见下面的 Demo)。
这是由于两个问题造成的:a)
rawQuery
方法只能用于返回作为输出 SQL 语句提取的数据,即 SELECT 语句或某些 PRAGMA 语句;b) 其他语句(例如 DELETE)不返回任何内容,实际上会导致回滚,撤销他们所做的事情。
您应该使用:-
一个
execSQL
方法,同样不返回结果,
exeSQL
做该做的事,可能什么也没有,或者失败,或者相应的便捷方法,例如
delete
删除方法。
便捷方法,除了执行操作之外,还返回适当的结果:-
insert
方法返回ROWID表的rowid或其别名delete
和 update
方法返回受影响的行数(删除或更新的行数)。即便捷方法在执行后调用适当的 SQLite API 函数以返回值
演示
以下为示范:-
execSQL
方法然后返回有用结果的示例,以及 delete
便捷方法以下是用于 Demo 的 DatabaseHelper 类,该类基于可以从您的代码中确定的内容:-
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);
}
}
deleteOne
方法的更正版本deleteByExecSQL
方法,使用execSQL方法进行删除,但也通过询问实际删除前后表中的行数并计算差值来返回已删除的行数。deleteViaConvenienceMethod
为了实际演示这 3 种方法,请使用以下活动代码:-
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();
}
}
}
运行时结果为:-
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
delete
方法的代码更简单、更高效(它使用适当的 SQLite 接口),并且不需要重新扫描表来获取计数