【问题标题】:Simulate ORDER BY in SQLite UPDATE to handle uniqueness constraint在 SQLite UPDATE 中模拟 ORDER BY 以处理唯一性约束
【发布时间】:2013-10-15 12:32:56
【问题描述】:

因此,我在 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

我希望在priority > 1 的所有单元格的priority 上加1。这是我的第一次尝试:

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

这失败了,可能是因为更新没有排序,允许更新尝试将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 一起使用,而后者也 does not 启用了 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 在提交事务之前检查了唯一性约束。

3 次失败的尝试,但我确信这是可能的。问题是:怎么做;在此范围内,如何做到最好

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

【问题讨论】:

    标签: sql sqlite android-sqlite


    【解决方案1】:

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

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

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

    【讨论】:

    • 有趣;谢谢!我还不知道priority 不包含负值的假设是否成立;因此,尽管我对您的回答表示赞成,但我没有将其标记为“已接受”。我一直在考虑尝试使用 COUNT 来建立偏移量以避免冲突,但该方法的成功将取决于不同的假设(即 priority 中的任何值都不会大于 @987654328 中的值@ 保证连续),我再次不确定其正确性。我更喜欢不依赖假设的解决方案。
    • (或者,更具体地说,基于未经检查的假设。)
    • 我以为你是这个数据库/应用程序的设计者或开发者,所以你知道需求/假设。
    • 这是一个已知问题,但不被视为错误:sqlite.org/src/tktview?name=fc6f41426b
    • 我很遗憾看到这被关闭为“不是错误”。他们还应该考虑更改关于 SQLite 页面中的这一行:“SQLite 是一个进程内库,它实现了一个自包含、无服务器、零配置、事务性 SQL 数据库引擎。”被认为是事务性 SQL 数据库引擎,直到它符合(或试图符合)SQL 标准——该标准明确规定应在语句结束时(或如果延迟)在事务结束时检查约束。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-19
    • 2022-01-09
    • 2015-04-22
    相关资源
    最近更新 更多