2

我是 PDO 事务的新手,遇到以下情况:我想从两个单独的表中删除,并规定如果任一删除失败,则两者都不应该发生。这似乎是交易的理想场景。我尝试了以下方法:

$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();
}

在第一个删除查询中,我查询了一些不正确的内容(即 table1 中没有 user_id 等于 1 的实例)。尽管如此,第二次删除还是通过了。这可能是预期的行为,我没有正确测试。

那么,我将如何使用事务正确编写此内容,以便两个删除都通过或都不通过?

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 中的删除,并且不要让数据从一个表中删除而不是另一个表。

如果其中任何一个不匹配任何行,听起来您想中止这两个删除。我已经扩展了上面的代码示例以显示更完整的示例。如果该示例没有使用事务对两个更改进行分组,它可能允许第一次删除成功,然后发现第二次删除没有删除任何内容。

于 2013-03-12T18:34:15.450 回答