9

我在 SQLite 3 中有一个表,因此:

sqlite> .schema
CREATE TABLE table1 (id INTEGER PRIMARY KEY NOT NULL,
                     title TEXT UNIQUE NOT NULL,
                     priority INTEGER UNIQUE NOT NULL);

以下是一些示例数据,用于说明:

sqlite> SELECT * FROM table1;
id          title       priority  
----------  ----------  ----------
1           a           1         
2           b           2         
3           c           3         
4           d           4

我希望将 1 添加到priority所有单元格中priority > 1。这是我的第一次尝试:

sqlite> UPDATE table1 SET priority = priority + 1 WHERE priority > 1;
Error: column priority is not unique

这失败了,大概是因为更新没有排序,允许 UPDATE 尝试将priority列中的一个单元格设置为现有单元格的值。所以,这是我的第二次尝试:

sqlite> UPDATE table1 SET priority = priority + 1 WHERE priority > 1
        ORDER BY priority DESC;
Error: near "ORDER": syntax error

这也失败了,大概是因为我安装的 SQLite 3 没有使用SQLITE_ENABLE_UPDATE_DELETE_LIMIT选项编译。

因为我最终可能想在 Android 上将我的 SQL 语句与 SQLite 一起使用,而后者也没有启用 SQLITE_ENABLE_UPDATE_DELETE_LIMIT,所以我最好找到另一种方法来实现我的目标,而不是重新编译启用 SQLITE_ENABLE_UPDATE_DELETE_LIMIT 的 SQLite 3。那么,这是我的第三次尝试:

sqlite> BEGIN TRANSACTION;
        UPDATE table1 SET priority = priority + 1 WHERE priority > 1;
        END TRANSACTION;
Error: column priority is not unique

这也失败了,大概是因为 SQLite 在提交事务之前检查了唯一性约束。

三个失败的尝试,但我相信这是可能的。问题是:怎么做;在此范围内,如何最好地做到这一点

注意我宁愿不依赖任何未经检查的假设。

4

1 回答 1

12

问题出现是对的,因为 SQLite 在每次更新行后检查约束,而不是在语句结束或事务结束时检查约束。

我看到了这个问题的解决方法(SQLite 没有UPDATE正确实现)。假设该priority列没有任何负值,我们可以将它们(负值)用作临时值以避免UNIQUE约束错误:

UPDATE table1 SET priority = - (priority + 1) WHERE priority > 1 ;

UPDATE table1 SET priority = - priority WHERE priority < 0 ;
于 2013-10-15T12:41:11.647 回答