如何在SQLite中实现多语句事务的回滚?

问题描述 投票:0回答:1

在 macOS 上使用 sqlite3 3.43.2,我将以下内容输入到一个空的内存数据库中:

.mode markdown
.headers on

create table job(
    name text not null,
    billable real not null,
    check(billable > 0.0) on conflict abort
);

begin transaction;
insert into job values ("calibrate", 1.5);
insert into job values ("reset", -0.5);
insert into job values ("clean", 0.5);
commit;

select * from job;

我希望从最后的

select
中得不到任何结果,因为事务内的第二个
check
存在
insert
违规,但其他两个
insert
语句已执行:

Runtime error near line 12: CHECK constraint failed: billable > 0.0 (19)
|   name    | billable |
|-----------|----------|
| calibrate | 1.5      |
| clean     | 0.5      |
  1. 从表定义中删除
    on conflict abort
    不会改变此行为。
  2. 在表定义中将
    on conflict abort
    替换为
    on conflict rollback
    不会改变此行为。

好吧:让我们将错误处理移至

insert
语句。在新的内存数据库中:

create table job(
    name text not null,
    billable real not null,
    check(billable > 0.0)
);

begin transaction;
insert or rollback into job values ("calibrate", 1.5);
insert or rollback into job values ("reset", -0.5);
insert or rollback into job values ("clean", 0.5);
commit;

select * from job;

输出为:

Runtime error near line 12: CHECK constraint failed: billable > 0.0 (19)
Runtime error near line 14: cannot commit - no transaction is active
| name  | billable |
|-------|----------|
| clean | 0.5      |

这表明 SQLite 在该事务中的第二条语句中的错误之后

继续执行了事务中的第三条语句(其中插入了 
clean)。我预计当第二条语句中发生错误时,整个事务将中止,即 SQLite 甚至不会尝试第三条insert
。 (我的心理模型是用编程语言引发和捕获异常。)

最后,在另一个新数据库中:

insert or rollback into job values ("calibrate", 1.5); insert or rollback into job values ("reset", -0.5); insert or rollback into job values ("clean", 0.5);
产生:

Runtime error near line 11: CHECK constraint failed: billable > 0.0 (19) | name | billable | |-----------|----------| | calibrate | 1.5 | | clean | 0.5 |
这是我所期望的,但不是我想要的。

有没有办法在 SQLite 中创建真正的多语句事务?如果是这样,语法是什么?我想要类似的东西:

-- this is not valid SQLite syntax begin transaction; insert into job values ("calibrate", 1.5); insert into job values ("reset", -0.5); insert into job values ("clean", 0.5); commit or rollback;
但如前所述,这无法解析。期望的效果是,如果事务内的任何

语句失败,则回滚整个事务。 这可能是另一种可接受的行为吗?

sql sqlite transactions rollback
1个回答
0
投票

© www.soinside.com 2019 - 2024. All rights reserved.