【问题标题】:How to delete row from table based on text that is not primary key?如何根据不是主键的文本从表中删除行?
【发布时间】:2014-05-18 02:08:45
【问题描述】:

我在愿望清单应用程序中使用的 SQLite 数据库中有一个表。我希望能够在数据库中存储购买物品的历史记录。愿望清单中的每个项目都有一个详细视图,其中包含“已购买”复选框,用户可以单击以指示愿望清单中的项目已被购买。然后,我在用户可以单击的选项菜单中有一个单独的“历史”选项,它会显示一个由数据库中的项目填充的列表视图。

当我在其详细视图上选中“已购买”复选框并且名称显示在数据库的历史列表视图中时,我已经能够获取复选框的侦听器以使用其名称将项目添加到数据库中。但是当我取消选中该框时,我试图用来从数据库中删除行的 sql 命令不起作用。它现在用来给出错误,它什么也不做。我已经包含了帮助程序类和我使用主代码中的名称添加和删除项目的代码部分。我想直接使用该项目的名称进行删除,而不是搜索 ID 号,然后查询该 ID 号以将其删除。我宁愿直接使用名称,因为我不担心删除重复项。我已经尝试阅读其他帖子和一些参考资料,但无法弄清楚我错过了什么。

ps。在删除语句 sql 中,我尝试不使用“'”但出现错误。这样我什么都得不到。它只是不会将其从视图中删除。

来自 DBHelper 的代码

public class DBHelper extends SQLiteOpenHelper {

private static final String DB_NAME = "goodthings2.db";
private static final int DB_VERSION = 2;

public static final String TABLE_THINGS = "things";
public static final String C_ID = "_id";
public static final String C_TITLE = "title";
public static final String C_PRICE = "price";
public static final String C_DATE = "date";

public DBHelper(Context context){
    super(context, DB_NAME, null, DB_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {

    final String sqlCreateTablePeople = 
            "CREATE TABLE " + TABLE_THINGS + 
            "( " + C_ID + " integer primary key autoincrement, " 
                 + C_TITLE + " text not null );";

    db.execSQL(sqlCreateTablePeople);

}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    final String sqlDropTablePeople = "DROP TABLE IF EXISTS " + TABLE_THINGS +  
";";
    db.execSQL(sqlDropTablePeople);
    onCreate(db);

}

}

愿望清单项目详细视图的片段代码部分:

    mPurchasedCheckBox.setOnCheckedChangeListener(
        new OnCheckedChangeListener(){
            public void onCheckedChanged(CompoundButton buttonView, 
boolean isChecked){

            mThing.setPurchased(isChecked);
            //Toast.makeText(getActivity(), 
mThing.getTitle().toString(), Toast.LENGTH_LONG).show();

            //String name = mThing.getTitle().toString();

            if(isChecked == true){
                Toast.makeText(getActivity(), "isChecked = true",  
Toast.LENGTH_LONG).show();

                // add the new data to the db
                DBHelper helper = new DBHelper(getActivity());
                SQLiteDatabase db = helper.getWritableDatabase();
                ContentValues cv = new ContentValues();
                cv.put(DBHelper.C_TITLE, 
mThing.getTitle().toString());
                //cv.put(DBHelper.C_PRICE, 
mThing.getPrice().toString());
                //cv.put(DBHelper.C_DATE, 
mThing.getDate().toString());
                //cv.put(DBHelper.C_ID, mThing.getId().toString());
                db.insert(DBHelper.TABLE_THINGS, null, cv);
                db.close();


            }else{

                Toast.makeText(getActivity(), "isChecked = false",  
Toast.LENGTH_LONG).show();

                /*SQLiteDatabase db = new  
DBHelper(getActivity()).getWritableDatabase();

                int rowsAffected = -1;

                rowsAffected = db.delete(DBHelper.TABLE_THINGS,  
DBHelper.C_ID + " = " + mThing.getId().toString(), null);

                Toast.makeText(getActivity(), "rowsAffected = " +  
rowsAffected, Toast.LENGTH_LONG).show();

                db.close();*/

                DBHelper helper = new DBHelper(getActivity());

                SQLiteDatabase db = helper.getWritableDatabase();

                db.execSQL("delete from " + DBHelper.TABLE_THINGS +  
" where " + DBHelper.C_TITLE + " = " + " ' " +  mThing.getTitle().toString() + " ' " );

            }
        }

    });

【问题讨论】:

  • 大小写例如 "My Title" != "My title" ?
  • 您没有显示 SQL 查询或用于填充 ListView 的适配器类型。如果您使用SELECT * ... 查询和SimpleCursorAdapter,那么您显然不需要在ListView 行中显示“ID”,但仍然可以从Cursor 访问每一行。就个人而言,我宁愿使用唯一的“id”,也不愿基于匹配的文本字符串。如果有人在他们的愿望清单中添加了两件或更多相同的物品,但只购买了一件怎么办?通过文本匹配删除将从列表中删除所有内容。

标签: android sql sqlite sql-delete


【解决方案1】:

条件参数未正确构建:

 DBHelper.C_TITLE + " = " + " ' " +  mThing.getTitle().toString() + " ' " );

引号之间的空格会导致参数在开头和结尾有多余的空格(例如'The Title'而不是'The Title',因此找不到要删除的记录)。

建议:不要像这样构建自定义SQL语句来删除行,改用SQLiteDatabase.delete()方法。如果需要,这将正确地转义参数。否则您的应用程序将暴露给SQL injection。作为额外奖励,结果会告诉您删除了多少条记录。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-23
    相关资源
    最近更新 更多