【问题标题】:sqlite transactions do not respect deletesqlite 事务不尊重删除
【发布时间】:2014-05-06 12:42:12
【问题描述】:

我需要修改表格中的所有内容。所以我将修改包装在一个事务中,以确保所有操作都成功,或者都不成功。我从 DELETE 语句开始修改,然后是 INSERT。我发现即使 INSERT 失败,DELETE 仍然发生,并且数据库没有回滚到事务前状态。

我创建了一个示例来演示这个问题。将以下命令放入名为EXAMPLE.SQL 的脚本中

CREATE TABLE A(id INT PRIMARY KEY, val TEXT);

INSERT INTO A VALUES(1, “hello”);

BEGIN;
     DELETE FROM A;
     INSERT INTO A VALUES(1, “goodbye”);  
     INSERT INTO A VALUES(1, “world”);
COMMIT;

     SELECT * FROM A;

如果你运行脚本:“sqlite3 a.db

SQL error near line 10: column id is not unique
1|goodbye

令人惊讶的是,SELECT 语句的结果并没有显示“1|hello”。

看起来 DELETE 成功了,第一个 INSERT 成功了。但是,当第二次 INSERT 失败时(如预期的那样)......它没有 ROLLBACK 数据库。

这是一个 sqlite 错误吗?还是我对应该发生的事情的理解有误?

谢谢

【问题讨论】:

    标签: sqlite


    【解决方案1】:

    它可以正常工作。

    COMMIT 提交事务中的所有操作。涉及world的那个有问题,所以没有包含在交易中。

    要取消交易,请使用ROLLBACK,而不是COMMIT。没有自动 ROLLBACK 除非您将其指定为冲突解决方案,例如INSERT OR ROLLBACK INTO ....

    并使用' 单引号而不是 作为字符串文字。

    【讨论】:

    • 正确。谢谢。仅供参考——我使用 sqlite 命令外壳作为概念证明。实际的解决方案将在代码中,在这种情况下,我们显然会进行回滚。非常感谢。
    【解决方案2】:

    This documentation 显示导致自动回滚的错误类型:

    SQLITE_FULL: database or disk full
    SQLITE_IOERR: disk I/O error
    SQLITE_BUSY: database in use by another process
    SQLITE_NOMEM: out or memory
    SQLITE_INTERRUPT: processing interrupted by application request 
    

    对于其他错误类型,您需要捕获错误并回滚,this SO question 对此进行了详细介绍。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-06
      • 2016-06-20
      • 1970-01-01
      • 2017-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多