在 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 |
on conflict abort
不会改变此行为。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;
但如前所述,这无法解析。期望的效果是,如果事务内的任何语句失败,则回滚整个事务。 这可能是另一种可接受的行为吗?