【问题标题】:How to update and increment a database?如何更新和增加数据库?
【发布时间】:2019-04-28 08:08:35
【问题描述】:

我有一个有效的删除功能的代码。 db 中的列是 COL_TASK_TITLE 和 COL_NUM 。我的增量功能不起作用。我还提供了下面的删除功能,它完全可以工作。

   public void deleteTask(View view) {

        View parent = (View) view.getParent();
        TextView taskTextView = (TextView) 
        parent.findViewById(R.id.task_title);
        String task = String.valueOf(taskTextView.getText());
        SQLiteDatabase db = mHelper.getWritableDatabase();
        db.delete(TaskContract.TaskEntry.TABLE,
        TaskContract.TaskEntry.COL_TASK_TITLE + " = ?",
        new String[]{task});
        db.close();
        updateUI();
    }


    public void incrment(View view) {
        View parent = (View) view.getParent();
        TextView taskTextView = (TextView) 
        parent.findViewById(R.id.task_title);
        String task = String.valueOf(taskTextView.getText());
        SQLiteDatabase db = mHelper.getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put("COL_NUM",COL_NUM+1)
        db.update(TaskContract.TaskEntry.TABLE,cv
            TaskContract.TaskEntry.COL_TASK_TITLE + " = ?",
            new String[]{task});
        db.close();
        updateUI();
    }

【问题讨论】:

  • increment() 的目的是什么?我高度怀疑你实际上根本不需要它。

标签: java android database sqlite android-sqlite


【解决方案1】:

我猜COL_NUM 是列的名称,对吧?
所以这一行是错误的:

cv.put("COL_NUM", COL_NUM + 1);

因为您认为您在列的值中添加了一个数字,实际上您将1 连接到列的名称。
您必须做的是将当前值增加 1,如下所示:

db.execSQL(
    "update " + TaskContract.TaskEntry.TABLE + 
    " set " + COL_TaskContract.TaskEntry.COL_NUM + " = " + COL_TaskContract.TaskEntry.COL_NUM + " + 1" + 
    " where " + TaskContract.TaskEntry.COL_TASK_TITLE + " = ?", new Object[] {task});

如果存在COL_NUMnull 的情况,则将语句更改为:

db.execSQL(
    "update " + TaskContract.TaskEntry.TABLE + 
    " set " + COL_TaskContract.TaskEntry.COL_NUM + " = coalesce(" + COL_TaskContract.TaskEntry.COL_NUM + ", 0) + 1" + 
    " where " + TaskContract.TaskEntry.COL_TASK_TITLE + " = ?", new Object[] {task});

所以把你的方法改成这样:

public void incrment(View view) {
    View parent = (View) view.getParent();
    TextView taskTextView = (TextView) parent.findViewById(R.id.task_title);
    String task = taskTextView.getText().toString();
    SQLiteDatabase db = mHelper.getWritableDatabase();
    db.execSQL(
        "update " + TaskContract.TaskEntry.TABLE +
        " set " + COL_TaskContract.TaskEntry.COL_NUM + " = coalesce(" + COL_TaskContract.TaskEntry.COL_NUM + ", 0) + 1" +
        " where " + TaskContract.TaskEntry.COL_TASK_TITLE + " = ?", new Object[] {task}
    );
    db.close();
    updateUI();
}

当然你可以像你一样使用update()方法,但是首先你应该找到COL_NUM中的现有值,增加它,把它放在cv中,然后执行update()

【讨论】:

  • new Object() {task} not work object[] (String,byte[],Long,Double) 仅适用。 new Object[]{task} 其他 new String[]{task} 你必须使用。你必须阅读 doco。
  • 错误给出未知类。 doco 说 Object[] bindArgs 所以需要对象数组(object[])而不是对象。找出你说的测试答案。
  • @Halcn 对。我用括号代替方括号。谢谢。
【解决方案2】:

当您使用更新方法时,ContentValues put 的第二个参数中的值(即 COL_NUM+1)被视为字符串并用单引号括起来,因此结果值变为字符串 COL_NUM1 最终是存储在第一个参数指定的列中的值。

  • 值的封闭至少部分是为了提供对 SQL 注入的保护。但是,在这种情况下,这有点碍事。

在这种情况下,您可以通过 execSQL 方法直接执行 SQL。为了防止 SQL 注入,您可以使用带有两个参数的 execSQL。第二个参数是将替换的参数?占位符。 execSQL.

  • 它说 执行一个不是 SELECT/INSERT/UPDATE/DELETE 的单个 SQL 语句。 实际上并非如此。相反,它是(应该是)一个警告(来自不带第二个参数的 execSQL)
  • 没有办法返回任何数据(比如受影响的人数 行)。相反,我们鼓励您使用 insert(java.lang.String, java.lang.String, android.content.ContentValues), 更新(java.lang.String,android.content.ContentValues, java.lang.String、java.lang.String[]) 等,如果可能的话。

即运行SQL UPDATE the_table SET COL_NUM = COL_NUM + 1 WHERE COL_TASK_TITLE = the_title

  • (其中 the_table 和 the_title 相应更改)。

  • update 方法生成并执行 SQL UPDATE the_table SET COL_NUM = 'COL_NUM1' WHERE COL_TASK_TITLE = 'the_title'。因此问题。

您可以使用以下方法:-

public void incrment(View view) {
    View parent = (View) view.getParent();
    TextView taskTextView = (TextView) 
    parent.findViewById(R.id.task_title);
    String task = String.valueOf(taskTextView.getText());        
    SQLiteDatabase db = mHelper.getWritableDatabase();

    db.execSQL(
            "UPDATE " + TaskContract.TaskEntry.TABLE +
            " SET " + TaskContract.TaskEntry.COL_NUM + " = " + 
            TaskContract.TaskEntry.COL_NUM + "+ 1 " +
            " WHERE " + TaskContract.TaskEntry.COL_TASK_TITLE + " = ?",
            new String[]{task}
    );

    /*
    // Alternative with COL_NUM hard coded rather than retrieved via TaskContract.TaskEntry.COL_NUM
    db.execSQL("UPDATE " + TaskContract.TaskEntry.TABLE +
            " SET COL_NUM  = COL_NUM + 1 " +
            "WHERE " +TaskContract.TaskEntry.COL_TASK_TITLE + " = ?"
            ,new String[]{task}
            );
    */
    db.close();
    updateUI();
}
  • 这假设 TaskContract.TaskEntry.COL_NUM 已定义(对名称使用单一来源可减少出错的机会,如果没有,则使用使用硬编码 COL_NUM 的注释掉替代方案(删除或注释掉 db.当前使用的 execSQL)

【讨论】:

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