【问题标题】:SQLite (Android) : UPDATE query with ORDER BYSQLite (Android):使用 ORDER BY 更新查询
【发布时间】:2019-02-18 12:19:35
【问题描述】:

Android,SQLite:我想在 myTable 中的其他行之间插入行,使用 android 中的 SQLite。为此,我试图增加从第 3 行开始的所有行的 id。这样​​我就可以在第 3 行插入一个新行。

myTable 的主键是列 id。表中没有其他约束。

我已经尝试使用https://stackoverflow.com/a/9177264/6671004 中提到的查询。此查询确实mySQL 中有效,但在 Android (SQLite) 中无效

这是代码行:

database.execSQL("UPDATE myTable SET id = (id + 1) where id > 2 ORDER BY id desc");

这是我在 Android Studio 上遇到的错误(编译时): https://imgur.com/a/9r0iyAa

这是我从查询中删除“ORDER BY id DESC”时遇到的异常:

java.lang.RuntimeException:无法启动活动 ComponentInfo{...}:android.database.sqlite.SQLiteConstraintException:唯一约束失败:myTable.id(代码 1555)

这是正确的方法吗?还是有更好的办法?

【问题讨论】:

  • Is this the correct way to do this? ORDER BY 子句适用于查询 (SELECT ...),不适用于命令。在插入或更新数据时,您不应该关心排序顺序,只在演示时关心,如果这很重要的话。
  • 您的第一个错误是尝试使用 rowid 来确定排序。不要那样做。
  • @Fantômas 我同意,但我有一个场景,这似乎是最好的选择,有什么办法可以做到吗?
  • 据我了解,每个插入/更新操作都会在 DB 中进行内部锁定,以便其他写入也需要一些时间进行读取,并且直到事务完成其他读取无法获得更新,所以顺序更新是从 sqlite 内部完成的,应该不会影响。但是这里给出的错误是因为您已将“id”设置为唯一字段,并使用已经存在的 id 值更新它将通过约束错误。

标签: android sql database sqlite


【解决方案1】:

正如许多人指出的那样,这绝对不是正确的方法。

但我找到了解决方法,以防其他人正在寻找类似的实现。

这里是:

UPDATE myTable SET id = - (id + 1) WHERE id > 1;
UPDATE myTable SET id = - id WHERE id < 0;

这是我发现的一个 hack here

再说一次,这不是正确的做法。但只是发布了一个我发现的工作解决方案。

【讨论】:

    【解决方案2】:

    我尝试过使用中提到的查询 https://stackoverflow.com/a/9177264/6671004。此查询确实适用于 mySQL 但在 Android (SQLite) 中没有

    那个问题被标记为 MYSQL。 MYSQL 与 SQLite 有很多不同之处。

    这是代码行:

    database.execSQL("UPDATE myTable SET id = (id + 1) where id > 2 ORDER BY id desc");

    SQLite UPDATE SQL 采用以下形式:-

    • 即没有 ORDER BY 子句,因此错误说如果你要使用任何 KEYWORD 那么它必须是 BETWEEN 或 IN 或 ; (当然你也可以使用 AND 扩展条件或等等)。

    如果我从中删除 'ORDER BY id DESC' 查询:

    原因是 rowid(id 是 rowid 的别名)具有隐含的 UNIQUE 约束,并且行将根据 更新id 列的顺序。因此,如果有超过 3 行(或者已经存在并且最后一行从未被删除),那么当 id 为 3 时,将存在 4 行并且 3 + 1 = 4 因此该行已经存在,因此 UNIQUE 约束遇到了。

    我想使用 SQLite 在 myTable 的其他行之间插入行 安卓。为此,我正在尝试增加所有行的 id 从第 3 行开始。这样我就可以在第 3 位置插入一个新行。

    简而言之,这不是一个好主意,实际上绝对不需要。

    这是正确的方法吗?还是有更好的办法?

    绝对

    您可能需要一个很好的人类可以理解的值,这样您就可以知道发生了什么。例如,您可以显示一个带有序列的列表,然后您可以说删除序列为 3 的行,从而将其等同于 id 列。很好,直到您以可能对用户更友好的不同顺序显示列表。突然你的序列变得复杂甚至无用,如果显示混乱。

    id标识符旨在识别行并允许快速访问该行,因为数字索引将更有效(比人类易于阅读的非数字索引)处理。它们还可以减少不必要的额外处理(移动数据)。

    一种有效的方法是通过将 id 绑定到列表中的位置来呈现列表(因此位置可以是包含相应 id 的数组的第 n 个元素,重新生成列表(底层数组)根据不同的顺序,因此第 n 个元素仍将具有各自的 id)。

    开始移动行的过程将导致额外的资源使用,例如额外的磁盘 IO,其成本相对较高。这将因您必须以相反的顺序处理行以绕过 UNIQUE 约束的事实而更加复杂,这本身将需要使用更昂贵的方法,因为默认情况下 SQLite 将尝试有效地执行更新而不是迎合用于偏离利用潜在效率的公认/接受技术所需的效率。

    【讨论】:

    • SQLite 现在支持 ORDER BY 和 LIMIT 子句:sqlite.org/lang_update.html - 2.3
    • @Ryan ORDER BY 不会影响行更新的顺序。这是您提供的链接中的引述:“UPDATE 语句上的 ORDER BY 子句仅用于确定哪些行属于 LIMIT。修改行的顺序是任意的,不受 ORDER BY 子句的影响。” .理解这一点非常重要。
    猜你喜欢
    • 1970-01-01
    • 2018-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-28
    • 2014-01-27
    • 1970-01-01
    • 2020-11-19
    相关资源
    最近更新 更多