SQLite:批量更新 'boolean' 列
SQLite: bulk update a 'boolean' column
在 SQL (SQLite) table 中更新布尔列(即分类二进制 INTEGER
值)的标准方法是什么?
(此处二进制意指仅采用两个值的整数:0
和 1
,因此问题标题中的引号)
给定一个 table:
CREATE TABLE types (
id INTEGER NOT NULL PRIMARY KEY,
name TEXT,
enabled INTEGER DEFAULT 1)
还有一个 objects 的列表,它可以有一个 enabled/disabled 状态并且表示为两个列表:
List<Long> idsEnabled = new ArrayList<>();
List<Long> idsDisabled = new ArrayList<>();
这是存储启用状态的正确方法吗(即 0
或 1
)?
SQLiteDatabase db = dbHelper.getWritableDatabase();
// upd: NOT WORKING because rawQuery does NOT work for modifying data,
// must use execSQL
db.rawQuery("UPDATE types set enabled=1 where id in ("
+ TextUtils.join(",", idsEnabled) + ")", null);
db.rawQuery("UPDATE types set enabled=0 where id in ("
+ TextUtils.join(",", idsDisabled) + ")", null);
是否有更好、更有效的 OOTB 方式来做到这一点?我的假设是,逐行更新每一行是最坏的情况。
问题不一定是 android-specific,尽管如果有一些 android-specific API 这样做会有所帮助。
方法rawQuery()
不是更新table的方法。
它用于return行,形式为Cursor
.
在这种情况下,您必须使用 execSQL()
:
if (idsEnabled.size() > 0 || idsDisabled.size() > 0) {
String ids1 = TextUtils.join(",", idsEnabled);
String ids0 = TextUtils.join(",", idsDisabled);
String sql =
"UPDATE types " +
"SET enabled = CASE " +
(idsEnabled.size() > 0 ? "WHEN id IN (" + ids1 + ") THEN 1 " : "") +
(idsDisabled.size() > 0 ? "WHEN id IN (" + ids0 + ") THEN 0 " : "") +
"ELSE enabled " +
"END";
db.execSQL(sql);
}
以上语句使用 CASE
表达式来确定将更新列当前值的值。
如果您只想更新 table 的一小部分,那么在 UPDATE
语句中包含一个 WHERE
子句会更有效,因此您可以省略ELSE
CASE
表达式的一部分:
if (idsEnabled.size() > 0 || idsDisabled.size() > 0) {
String ids1 = TextUtils.join(",", idsEnabled);
String ids0 = TextUtils.join(",", idsDisabled);
String idsAll = "";
if (idsEnabled.size() == 0) idsAll = ids0;
else if (idsDisabled.size() == 0) idsAll = ids1;
else idsAll = ids1 + "," + ids0;
String sql =
"UPDATE types " +
"SET enabled = CASE " +
(idsEnabled.size() > 0 ? "WHEN id IN (" + ids1 + ") THEN 1 " : "") +
(idsDisabled.size() > 0 ? "WHEN id IN (" + ids0 + ") THEN 0 " : " ") +
"END " +
"WHERE id IN (" + idsAll + ")";
db.execSQL(sql);
}
在 SQL (SQLite) table 中更新布尔列(即分类二进制 INTEGER
值)的标准方法是什么?
(此处二进制意指仅采用两个值的整数:0
和 1
,因此问题标题中的引号)
给定一个 table:
CREATE TABLE types (
id INTEGER NOT NULL PRIMARY KEY,
name TEXT,
enabled INTEGER DEFAULT 1)
还有一个 objects 的列表,它可以有一个 enabled/disabled 状态并且表示为两个列表:
List<Long> idsEnabled = new ArrayList<>();
List<Long> idsDisabled = new ArrayList<>();
这是存储启用状态的正确方法吗(即 0
或 1
)?
SQLiteDatabase db = dbHelper.getWritableDatabase();
// upd: NOT WORKING because rawQuery does NOT work for modifying data,
// must use execSQL
db.rawQuery("UPDATE types set enabled=1 where id in ("
+ TextUtils.join(",", idsEnabled) + ")", null);
db.rawQuery("UPDATE types set enabled=0 where id in ("
+ TextUtils.join(",", idsDisabled) + ")", null);
是否有更好、更有效的 OOTB 方式来做到这一点?我的假设是,逐行更新每一行是最坏的情况。
问题不一定是 android-specific,尽管如果有一些 android-specific API 这样做会有所帮助。
方法rawQuery()
不是更新table的方法。
它用于return行,形式为Cursor
.
在这种情况下,您必须使用 execSQL()
:
if (idsEnabled.size() > 0 || idsDisabled.size() > 0) {
String ids1 = TextUtils.join(",", idsEnabled);
String ids0 = TextUtils.join(",", idsDisabled);
String sql =
"UPDATE types " +
"SET enabled = CASE " +
(idsEnabled.size() > 0 ? "WHEN id IN (" + ids1 + ") THEN 1 " : "") +
(idsDisabled.size() > 0 ? "WHEN id IN (" + ids0 + ") THEN 0 " : "") +
"ELSE enabled " +
"END";
db.execSQL(sql);
}
以上语句使用 CASE
表达式来确定将更新列当前值的值。
如果您只想更新 table 的一小部分,那么在 UPDATE
语句中包含一个 WHERE
子句会更有效,因此您可以省略ELSE
CASE
表达式的一部分:
if (idsEnabled.size() > 0 || idsDisabled.size() > 0) {
String ids1 = TextUtils.join(",", idsEnabled);
String ids0 = TextUtils.join(",", idsDisabled);
String idsAll = "";
if (idsEnabled.size() == 0) idsAll = ids0;
else if (idsDisabled.size() == 0) idsAll = ids1;
else idsAll = ids1 + "," + ids0;
String sql =
"UPDATE types " +
"SET enabled = CASE " +
(idsEnabled.size() > 0 ? "WHEN id IN (" + ids1 + ") THEN 1 " : "") +
(idsDisabled.size() > 0 ? "WHEN id IN (" + ids0 + ") THEN 0 " : " ") +
"END " +
"WHERE id IN (" + idsAll + ")";
db.execSQL(sql);
}