我相信您的问题,正如您所描述的,与这一行有关:-
db.update(TaskContract.TaskEntry.TABLE_NAME, cv, String.valueOf(idx1), null);
特别是第三个(WHERE 子句)参数,即String.valueOf(idx1)
您实际上是在说 WHERE n(n 是列 TaskContract.TaskEntry.COLUMN_DATE 的偏移量/索引)。如果此列索引大于 0,则表达式将有效地为真,因此将更新每一行。
因此,此更新只需执行一次,如果列索引大于 0 (true),它将更新所有行。这似乎是您所描述的行为。
您需要参数类似于TaskContract.TaskEntry.COLUMN_DATE = 'CurrentDate'。
或者最好是TaskContract.TaskEntry.COLUMN_DATE=?,第四个参数解析 ? 占位符,例如newString[]{dateDB}.
这将使用该日期更新所有行,这可能会导致不必要的更新尝试。例如,如果您有两个相同的过去日期,则当光标到达该行和到达另一行时,两者都会更新。
我建议只提取要更新的行,这并不容易,因为您似乎将日期存储为 dd/mm/yyyy(根据日期顺序不容易排序)。但是,您可以通过在提取的光标中创建一个列来重新格式化日期并允许对其进行检查来解决此问题。
这看起来有点复杂,这里有一个例子:-
String TEMPPCOLNAME = "checkdate";
Cursor csr = db.query(TBNAME,new String[]{
// All existing columns
"*",
"rowid as uid",
// generate reformatted date column named checkdate usable by date functions
// i.e. converts dd/mm/yyyy to yyyy-mm-yy
"substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",7,4)||'-'||" +
"substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",4,2)||'-'||" +
"substr( " + TaskContract.TaskEntry.COLUMN_DATE + ",1,2) AS " + TEMPPCOLNAME },
// where clause to only include properly formatted dates and those who date is less
// than or equaly to today's date
TEMPPCOLNAME + "<= date('now') AND " +
"substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",3,1) = '/' AND " +
"substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",6,1) = '/'",
null,null,null,null
);
这是说得到一个包含表中所有列的游标 (*),使游标有一个名为 uid 的列,它是 rowid 的别名,并且使光标有一个名为 checkdate 的列(名称根据 TEMPCOLNAME)。 checkdate 是重新格式化的日期(现在是 SQLite 喜欢的 yyyy-mm-dd)
WHERE 子句(第三个参数)用于仅选择小于或等于第四个参数中定义的日期的日期,该参数将替换 ? 占位符。
WHERE 参数还将所选行限制为日期在位置 3 和 6 处具有 / 的行(仅作为预防措施)。
更新非常简单,重要的是特定于单行(因此提取列 uid 的原因):-
while (csr.moveToNext()) {
ContentValues cv = new ContentValues();
cv.put(TaskContract.TaskEntry.COLUMN_DATE,
new SimpleDateFormat("dd/MM/yyyy").format(Calendar.getInstance().getTime()));
db.update(TBNAME,cv,"rowid=?",new String[]{
String.valueOf(csr.getLong(csr.getColumnIndex("uid")))}
);
}
csr.close();
结合两者,您可以:-
public void updateDates2() {
String TEMPPCOLNAME = "checkdate";
Cursor csr = db.query(TaskContract.TaskEntry.TABLE_NAME,new String[]{
// All existing columns
"*",
"rowid as uid",
// generate reformatted date column named checkdate usable by date functions
// i.e. converts dd/mm/yyyy to yyyy-mm-yy
"substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",7,4)||'-'||" +
"substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",4,2)||'-'||" +
"substr( " + TaskContract.TaskEntry.COLUMN_DATE + ",1,2) AS " + TEMPPCOLNAME },
// where clause to only include properly formatted dates and those who date is less
// than or equaly to today's date
TEMPPCOLNAME + "<= date('now') AND " +
"substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",3,1) = '/' AND " +
"substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",6,1) = '/'",
null,null,null,null
);
while (csr.moveToNext()) {
ContentValues cv = new ContentValues();
cv.put(TaskContract.TaskEntry.COLUMN_DATE,
new SimpleDateFormat("dd/MM/yyyy").format(Calendar.getInstance().getTime()));
if (
db.update(TBNAME,cv,"rowid=?",new String[]{
String.valueOf(csr.getLong(csr.getColumnIndex("uid")))}
) > 0) {
Log.d("UPDT2","Row Updated OK.");
} else {
Log.d("UPDT2", "Update failed.");
}
}
csr.close();
}
使用上述测试提供了以下结果:-
10-27 09:32:51.482 4259-4259/? D/EVENTDATA: Row 1 - Event Name is Event1 Starts on 01/03/2011 Ends on 2021-03-21
10-27 09:32:51.482 4259-4259/? D/EVENTDATA: Row 2 - Event Name is Event2 Starts on 14/08/2014 Ends on 2020-03-21
10-27 09:32:51.482 4259-4259/? D/EVENTDATA: Row 3 - Event Name is Event3 Starts on 26/10/2017 Ends on 2017-12-21
10-27 09:32:51.482 4259-4259/? D/EVENTDATA: Row 4 - Event Name is Event4 Starts on 28/10/2017 Ends on 2018-21-31
10-27 09:32:51.482 4259-4259/? D/EVENTDATA: Row 5 - Event Name is Event5 Starts on 01/01/2018 Ends on 2018-12-31
10-27 09:32:51.482 4259-4259/? D/EVENTDATA: Row 6 - Event Name is Event6 Starts on 27/10/2018 Ends on 2018-12-31
10-27 09:32:51.482 4259-4259/? D/EVENTDATA: Row 7 - Event Name is Event7 Starts on garbage Ends on 2018-12-31
10-27 09:32:51.483 4259-4259/? D/UPDT2: Extracted Row for Event Event1 StartDate Stored = 01/03/2011 Converted to = 2011-03-01
10-27 09:32:51.487 4259-4259/? D/UPDT2: Row Updated OK.
10-27 09:32:51.487 4259-4259/? D/UPDT2: Extracted Row for Event Event2 StartDate Stored = 14/08/2014 Converted to = 2014-08-14
10-27 09:32:51.491 4259-4259/? D/UPDT2: Row Updated OK.
10-27 09:32:51.491 4259-4259/? D/UPDT2: Extracted Row for Event Event3 StartDate Stored = 26/10/2017 Converted to = 2017-10-26
10-27 09:32:51.495 4259-4259/? D/UPDT2: Row Updated OK.
10-27 09:32:51.495 4259-4259/? D/EVENTDATA: Row 1 - Event Name is Event1 Starts on 27/10/2017 Ends on 2021-03-21
10-27 09:32:51.495 4259-4259/? D/EVENTDATA: Row 2 - Event Name is Event2 Starts on 27/10/2017 Ends on 2020-03-21
10-27 09:32:51.495 4259-4259/? D/EVENTDATA: Row 3 - Event Name is Event3 Starts on 27/10/2017 Ends on 2017-12-21
10-27 09:32:51.495 4259-4259/? D/EVENTDATA: Row 4 - Event Name is Event4 Starts on 28/10/2017 Ends on 2018-21-31
10-27 09:32:51.495 4259-4259/? D/EVENTDATA: Row 5 - Event Name is Event5 Starts on 01/01/2018 Ends on 2018-12-31
10-27 09:32:51.495 4259-4259/? D/EVENTDATA: Row 6 - Event Name is Event6 Starts on 27/10/2018 Ends on 2018-12-31
10-27 09:32:51.495 4259-4259/? D/EVENTDATA: Row 7 - Event Name is Event7 Starts on garbage Ends on 2018-12-31
前 7 行是上述运行之前的数据,后 7 行是运行之后的数据。之间的 6 行是更新本身的形式 (我删除了生成提取行的代码.....,转换为是 checkdate 的值,即重新格式化的日期)
但是,也许最好的方法是进行一次更新,从而无需使用游标来提取行:-
public void updateDates() {
Calendar c = Calendar.getInstance();
SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
String formattedDate = formatter.format(c.getTime());
ContentValues cv = new ContentValues();
cv.put(TaskContract.TaskEntry.COLUMN_DATE,formattedDate);
String whereclause =
" substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",7,4)||" +
" substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",4,2)||" +
" substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",1,2) " +
" <= date('now') " +
" AND substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",3,1) = '/'" +
" AND substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",6,1) = '/'";
db.update(TaskContract.TaskEntry.TABLE_NAME,cv,whereclause,null);
}
测试数据:-
10-27 11:25:52.331 5250-5250/? D/EVENTDATA: Row 1 - Event Name is Event1 Starts on 01/03/2011 Ends on 2021-03-21
10-27 11:25:52.331 5250-5250/? D/EVENTDATA: Row 2 - Event Name is Event2 Starts on 14/08/2014 Ends on 2020-03-21
10-27 11:25:52.331 5250-5250/? D/EVENTDATA: Row 3 - Event Name is Event3 Starts on 26/10/2017 Ends on 2017-12-21
10-27 11:25:52.331 5250-5250/? D/EVENTDATA: Row 4 - Event Name is Event4 Starts on 28/10/2017 Ends on 2018-21-31
10-27 11:25:52.331 5250-5250/? D/EVENTDATA: Row 5 - Event Name is Event5 Starts on 01/01/2018 Ends on 2018-12-31
10-27 11:25:52.331 5250-5250/? D/EVENTDATA: Row 6 - Event Name is Event6 Starts on 27/10/2018 Ends on 2018-12-31
10-27 11:25:52.332 5250-5250/? D/EVENTDATA: Row 7 - Event Name is Event7 Starts on garbage Ends on 2018-12-31
10-27 11:25:52.335 5250-5250/? D/EVENTDATA: Row 1 - Event Name is Event1 Starts on 27/10/2017 Ends on 2021-03-21
10-27 11:25:52.335 5250-5250/? D/EVENTDATA: Row 2 - Event Name is Event2 Starts on 27/10/2017 Ends on 2020-03-21
10-27 11:25:52.335 5250-5250/? D/EVENTDATA: Row 3 - Event Name is Event3 Starts on 26/10/2017 Ends on 2017-12-21
10-27 11:25:52.335 5250-5250/? D/EVENTDATA: Row 4 - Event Name is Event4 Starts on 28/10/2017 Ends on 2018-21-31
10-27 11:25:52.335 5250-5250/? D/EVENTDATA: Row 5 - Event Name is Event5 Starts on 01/01/2018 Ends on 2018-12-31
10-27 11:25:52.335 5250-5250/? D/EVENTDATA: Row 6 - Event Name is Event6 Starts on 27/10/2018 Ends on 2018-12-31
10-27 11:25:52.335 5250-5250/? D/EVENTDATA: Row 7 - Event Name is Event7 Starts on garbage Ends on 2018-12-31