PDO“全有或全无”删除交易

时间:2013-03-12 18:25:28

标签: php pdo transactions

我是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的实例)。尽管如此,第二次删除仍然存在。这可能是预期的行为,我没有正确测试。

那么,我如何才能正确地使用删除既可以执行也可以不执行?

2 个答案:

答案 0 :(得分: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中的删除,并且不要从一个表而不是另一个表中删除数据。

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

答案 1 :(得分:3)

仅仅因为你的第一个查询影响了0行并不意味着它会引发异常,所以没有什么可以捕获的。我不确定您是否接受了这项工作,但您可能希望使用PDOStatement::rowCount()来检查受DELETE影响的行数。