注意:RaiseError设置为false。
$dbh->begin_work;
$dbh->do("..."); # sql1, ok
$dbh->do("..."); # sql2, fails (e.g. syntax error)
$dbh->do("..."); # sql3, ok
$dbh->commit;
这将导致提交sql1和sql3的效果,这是不可取的,因为在这种情况下我希望SQL语句一起成功/失败。目前我的解决方法是:
eval {
local $dbh->{RaiseError} = 1;
$dbh->begin_work;
$dbh->do("..."); # sql1, ok
$dbh->do("..."); # sql2, fails (e.g. syntax error)
$dbh->do("..."); # sql3, ok
$dbh->commit;
};
$dbh->rollback if $@; # needed, RaiseError does not automatically rollback
但我不太喜欢它。还有另一种更容易的选择吗我更喜欢Postgres的行为:
$dbh->begin_work;
$dbh->do("..."); # sql1, ok
$dbh->do("..."); # sql2, fails (e.g. syntax error)
$dbh->do("..."); # sql3, ok but fail because transaction status is now aborted
$dbh->commit; # becomes rollback
答案 0 :(得分:2)
一个选项是围绕DBD :: SQLite的db句柄实现一个包装器,它可以跟踪错误状态并在发生错误后忽略命令,就像Pg一样。我没有看到DBD :: SQLite可以做到这一点的任何迹象,或者SQLite本身支持这种模式,所以你可能必须在包装器中实现它。
我最初认为您可能需要ON CONFLICT ROLLBACK
而非默认ON CONFLICT ABORT
,但更多阅读表明它无法完成此任务。
您可以设置冲突和错误处理解决策略。文档表明它可以在表或每个语句级别工作,但语法地图显示它实际上是逐列的,applying to things like NOT NULL constraints。
我不确定ON CONFLICT ROLLBACK
会使tx无效,而且我不确定它是否适用于所有错误。文档有点不清楚。它可能会将其回滚并进入下一个语句的自动提交模式,这也同样糟糕。