到目前为止,我有一些查询运行良好,但我想将它们包装在事务中以减少数据损坏的可能性。运行代码后,一切似乎都正常工作(即没有抛出异常),但查询永远不会提交到数据库。我查看了有关S.O.的其他问题,但我没有找到任何适用于我的情况的问题。
这是我的代码:
db::$pdo->beginTransaction(); // accesses PDO object method
try {
$sql = "INSERT INTO expenses SET date=:date, amount=:amount, accountId=:account; ";
$sql .= "UPDATE accounts SET balance = balance - :amount WHERE id = :account";
$s = db::$pdo->prepare($sql);
$s->bindValue(':date', $date);
$s->bindValue(':amount', $amount);
$s->bindValue(':account', $account);
$s->execute();
db::$pdo->commit();
echo 'success';
}
catch (PDOException $e) {
db::$pdo->rollback();
echo '<p>Failed: ' . $e->getMessage() . '</p>';
}
当我运行代码时,它会输出成功消息,但就像我说的,没有任何东西提交到数据库中。
由于它是相关的,我还应该注意我的PDO错误模式设置为ERRMODE_EXCEPTION
,所以我认为这不是导致问题的原因。我正在运行一个MySQL数据库(InnoDB)
有什么想法吗?
我不完全确定在单个查询语句中运行多个查询的工作原理(如果有效),因为我通常通过在准备/执行语句中单独运行每个查询来执行事务。事务仍将对所有更改进行排队,直到按预期提交/回滚。根据这个SO答案,它似乎有效,但是该示例不是绑定值,因此这可能是另一个问题。
我建议将查询拆分为多个准备/绑定/执行语句,它应该按预期工作。
成功消息将全部显示,因为它只是为了回响.. 如果你想只在执行后显示成功,你应该使用 if 语句.. 对于不提交部分,它可能是很多事情.. 你确定所有值都$date、$amount$account都提供了吗? 您也可以尝试从简单的插入开始,如果可行,请进行更新。
$sql = 'INSERT INTO expenses (date, amount, account)
VALUES(:date, :amount, :account)';
$stmt = $this->pdo->prepare($sql);
$stmt->bindValue(':date', $);
$stmt->bindValue(':amount', $amount);
$stmt->bindValue(':account', $account);
if($stmt->execute()) {
db::$pdo->commit();
echo 'success';
}
不确定 db::$pdo->commit(); 部分原因是我使用某种 OOP 方式,但希望这可能会有所帮助。
我在其中一个项目中遇到了类似的问题,请在您拥有的块之后添加另一个 catch 块,以便代码如下所示:
catch (PDOException $e) {
db::$pdo->rollback();
echo '<p>Failed: ' . $e->getMessage() . '</p>';
}
catch (Exception $exc) {
db::$pdo->rollback();
echo '<p>Failed: ' . $exc->getMessage() . '</p>';
}
它将允许您捕获除PDOException
以外的类的异常,因此您可以确保更多。
更新:
请考虑将两个查询拆分为 2 个 PDO 语句,如下所示:
$sql = "INSERT INTO expenses SET date=:date, amount=:amount, accountId=:account; ";
$s = db::$pdo->prepare($sql);
$s->bindValue(':date', $date);
$s->bindValue(':amount', $amount);
$s->bindValue(':account', $account);
$s->execute();
$sql2 = "UPDATE accounts SET balance = balance - :amount WHERE id = :account;";
$s2 = db::$pdo->prepare($sql2);
$s2->bindValue(':amount', $amount);
$s2->bindValue(':account', $account);
$s2->execute();
我在整个项目中都成功地使用了这种方法,所以我希望它可能会有所帮助。
不要使用 db::$pdo->commit();
用
$sql = "INSERT INTO expenses SET date=:date, amount=:amount, accountId=:account;";
$sql .= "UPDATE accounts SET balance = balance - :amount WHERE id = :account;COMMIT;"; // change here
有点傻;(