2

私はPDOトランザクションに不慣れで、次のシナリオがあります。2つの別々のテーブルから削除したいのですが、どちらかの削除が失敗した場合、どちらも発生しないという規定があります。これは、トランザクションにとって理想的なシナリオのようです。私は次のことを試しました:

$db->beginTransaction();

try {
    $db->exec( "DELETE FROM table1 WHERE galleryid = '$gallery_id' AND userid = '1'" );
    $db->exec( "DELETE FROM table2 WHERE galleryid = '$gallery_id'" );
    $db->commit();
} catch( PDOException $e ) {
    $db->rollBack();
    echo $e->getMessage();
}

最初の削除クエリで、真ではないものをクエリしました(つまり、user_idが1に等しいインスタンスはtable1にありません)。それにもかかわらず、2回目の削除が行われます。これは予想される動作である可能性があり、私はこれを適切にテストしていません。

では、両方の削除が通過するか、どちらも通過しないようなトランザクションを使用して、これを正しく書き込むにはどうすればよいでしょうか。

4

2 に答える 2

3

最初のクエリが0行に影響を与えるからといって、それが例外をスローすることを意味するわけではないので、キャッチするものは何もありません。それがあなたが求めているものであるかどうかはよくわかりませんが、PDOStatement::rowCount()の影響を受ける行数を確認するために使用することをお勧めしますDELETE

于 2013-03-12T18:36:15.673 に答える
3

DELETEがゼロ行に一致する場合、それは失敗またはエラーではありません。

DELETEが影響を与えた行数をテストする場合は、PDOStatement :: rowCount()を使用します。

次に例を示します。

$db->beginTransaction();
try {
    $del1 = $db->prepare( "DELETE FROM table1 WHERE galleryid = :galleryid AND userid = :userid" );
    $del1->execute(array(":galleryid"=>$gallery_id, ":userid"=>1));
    if ($del1->rowCount() < 1) {
      throw new RuntimeException("Delete from table1 matched no rows.")
    }

    $del2 = $db->prepare( "DELETE FROM table2 WHERE galleryid = :galleryid" );
    $del2->execute(array(":galleryid"=>$gallery_id));
    if ($del2->rowCount() < 1) {
      throw new RuntimeException("Delete from table2 matched no rows.")
    }

    $db->commit();
} catch( RuntimeException $e ) {
    $db->rollBack();
    echo $e->getMessage();
}

コメントを再確認してください。

これは、トランザクションの優れたアプリケーションです。つまり、table1とtable2からの削除を同時に適用し、一方のテーブルからデータを削除して、もう一方のテーブルからデータを削除しないようにする必要があります。

どちらかが行に一致しない場合は、両方の削除を中止したいようです。上記のコード例を拡張して、より完全な例を示しました。この例では、トランザクションを使用して2つの変更をグループ化していない場合、最初の削除が成功し、2番目の削除では何も削除されないことがわかります。

于 2013-03-12T18:34:15.450 に答える