使SQLite在事务错误方面更像Postgres?

时间:2012-08-22 10:46:55

标签: perl sqlite postgresql

注意: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

1 个答案:

答案 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无效,而且我不确定它是否适用于所有错误。文档有点不清楚。它可能会将其回滚并进入下一个语句的自动提交模式,这也同样糟糕。