3

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

1 に答える 1

2

1 つのオプションは、DBD::SQLite の db ハンドルの周りにラッパーを実装することです。エラー状態を追跡し、Pg と同じようにエラーの後にコマンドを無視します。DBD::SQLite がそれを実行できる、または SQLite がそのようなモードをネイティブにサポートしているという兆候は見られなかったので、おそらくラッパーで実装する必要があります。


ON CONFLICT ROLLBACK私は当初、 default の代わりに必要かもしれないと思っていON CONFLICT ABORTましたが、より多くの読書はそれが仕事をしないことを示唆しています.

競合およびエラー処理の解決戦略を設定できます。ドキュメントは、テーブルまたはステートメント レベルごとに機能することを示唆していますが、構文マップは、実際には列ごとであり、NOT NULL 制約などに適用されることを示しています。

tx が無効のままになるかどうかON CONFLICT ROLLBACKはわかりません。また、すべてのエラーに対して機能するかどうかもわかりません。ドキュメントはちょっと不明確です。ロールバックして、次のステートメントの自動コミット モードに入る可能性がありますが、これも同様に悪いことです。

于 2012-08-22T13:31:28.260 に答える