为什么这个PDO回滚不起作用?

时间:2012-02-23 17:37:28

标签: php mysql pdo

我在PHP和MySQL数据库中使用PDO。我想要做的是每当插入失败时(例如在唯一字段中重复输入),让它抛出异常错误消息并回滚更改(而不是在我的情况下自动递增)。

这就是我所做的,但它不起作用:

try {
    $email = $_POST['Email'];
    $FirstName = $_POST['FirstName'];
    $LastName = $_POST['LastName'];

    $query="INSERT INTO subscriber (Email,FirstName,LastName,CreateDate) VALUES (?,?,?,CURDATE())";
    $stmt = $conn->prepare($query);

    $stmt->bindParam(1, $email , PDO::PARAM_STR);
    $stmt->bindParam(2, $FirstName, PDO::PARAM_STR);
    $stmt->bindParam(3, $LastName, PDO::PARAM_STR);

    $stmt->execute();
}
catch(PDOException $e) {
    die ($e->getMessage().'<a href="addSub.php"> Back</a>'); 
    $conn->rollBack();
}

我哪里出错了?

这是它的编辑版本(对于插入的整个部分),这是正确的吗?谢谢

if($_SERVER['REQUEST_METHOD'] == "POST"){


$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->beingTransaction();
try {

    $email = $_POST['Email'];
    $FirstName = $_POST['FirstName'];
    $LastName = $_POST['LastName'];


    $query="INSERT INTO subscriber (Email,FirstName,LastName,CreateDate) VALUES (?,?,?,CURDATE())";
    $stmt = $conn->prepare($query);


    $stmt->bindParam(1, $email , PDO::PARAM_STR);
    $stmt->bindParam(2, $FirstName, PDO::PARAM_STR);
    $stmt->bindParam(3, $LastName, PDO::PARAM_STR);

    $conn->commit();

}
catch(PDOException $e)
    {
    die ($e->getMessage().'<a href="addSub.php"> Back</a>'); 
    $conn->rollBack();
    }


try {
    $userID = $_SESSION['username'];
    $query="INSERT INTO list_sub (SubID,ListID) VALUES ('',$_SESSION[ListID])";
    $stmt = $conn->prepare($query);

    $conn->commit();

}
catch(PDOException $e)
    {
    $conn->rollBack();
    die ($e->getMessage().'<a href="addSub.php"> Back</a>'); 
    }

$conn = null;
}

5 个答案:

答案 0 :(得分:9)

这就是所有的代码吗?您必须启动事务才能提交/回滚:

$conn->beginTransaction();

try {
    ....
    $conn->commit();
} catch (PDOException $e) {
    $conn->rollback();
}

答案 1 :(得分:6)

PHP函数dieexit的别名,并在打印指定的消息后立即终止执行,因此第二行 - 回滚 - 永远不会执行。

答案 2 :(得分:2)

首先,您使用die()将退出程序,因此不会执行任何行。

然而,除此之外,您还需要确定其他事项。

首先,确保subscriberInnoDB表格类型。 MySQL(MyISAM)上的默认表类型不支持事务。

其次,请确保您的PDO对象PDO::ATTR_ERRMODE设置为PDO::ERRMODE_EXCEPTION。您可以在构造函数中设置此属性,也可以使用setAttribute()

第三,您需要在$conn->beginTransaction()子句之前使用try实际开始交易。

答案 3 :(得分:1)

无法保证AUTOINCREMENT值是连续的。

如果有两个并行的事务,都插入到同一个表中,那么任何一个都接受编号中有漏洞,或者第二个事务必须等到第一个事务完成才能启动。由于这对性能不利,因此可以实现“漏洞可接受”的变体。

答案 4 :(得分:0)

Your put die...

  

此语言构造等同于exit()。

相关问题