drgbpq5930 2015-08-12 11:28
浏览 61
已采纳

为什么PDO rollback()需要closeCursor()才能反映在输出中?

In the following code, transaction fails and roll back is invoked.

However, in terms of the output:

If I remove the closeCursor(), payer`s balance is printed as -200$.

If I specify the closeCursor(), payer`s balance is printed as 0 which is the expected behavior.

This happens because result from the first select statement isn't being cleared before the second one is run.

Why do we need to close the connection for the roll back to be reflected in output? In both cases, roll back is invoked, so the value 0 is specified in DB. So I expect the balance to be printed as 0.

I dont see the relation between closing a connection DB, and getting latest DB values. Fetch() gets the value from DB, so if the value is 0, how come "it thinks" it`s -200?

This applies only to SQLite. MySQL will print 0 regardless if you use closeCursor().

<?php
try {
    require_once '../../includes/pdo_connect.php';
    // Set up prepared statements transfer from one account to another
    $amount = 0;
    $payee = 'John White';
    $payer = 'Jane Black';
    $debit = 'UPDATE savings SET balance = balance - :amount WHERE name = :payer';
    ####1st SQL#### $getBalance = 'SELECT balance FROM savings WHERE name = :payer';  
    $credit = 'UPDATE savings SET balance = balance + :amount WHERE name = :payee';

    $pay = $db->prepare($debit);
    $pay->bindParam(':amount', $amount);
    $pay->bindParam(':payer', $payer);

    $check = $db->prepare($getBalance);
    $check->bindParam(':payer', $payer);

    $receive = $db->prepare($credit);
    $receive->bindParam(':amount', $amount);
    $receive->bindParam(':payee', $payee);

    // Transaction
    $db->beginTransaction();
    $pay->execute();
    if (!$pay->rowCount()) {
        $db->rollBack();
        $error = "Transaction failed: could not update $payer's balance.";
    } else {
        // Check the remaining balance in the payer's account
        $check->execute();
        $bal = $check->fetchColumn();
        ########## $check->closeCursor(); 

        // Roll back the transaction if the balance is negative
        if ($bal < 0) {
            $db->rollBack();
            $error = "Transaction failed: insufficient funds in $payer's account.";
        } else {
            $receive->execute();
            if (!$receive->rowCount()) {
                $db->rollBack();
                $error = "Transaction failed: could not update $payee's balance.";
            } else {
                $db->commit();
            }
        }
    }
} catch (Exception $e) {
    $error = $e->getMessage();
}
?>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>PDO Transaction</title>
    <link href="../../styles/styles.css" rel="stylesheet" type="text/css">
</head>
<body>
<h1>PDO Transactions</h1>
<?php
if (isset($error)) {
    echo "<p>$error</p>";
}
?>
<table>
    <tr>
        <th>Name</th>
        <th>Balance</th>
    </tr>
            ####2nd SQL####<?php foreach ($db->query('SELECT name, balance FROM savings') as $row) { ?>
    <tr>
        <td><?php echo $row['name']; ?></td>
        <td>$<?php echo number_format($row['balance'], 2); ?></td>
    </tr>
    <?php } ?>
</table>
</body>
</html>
  • 写回答

1条回答 默认 最新

  • douhuitan5863 2015-08-13 15:29
    关注

    The above reply by Ryan Vincent is the correct one.

    So I am specifying this to mark my question as solved.

    Thanks,

    Qwerty

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 乌班图ip地址配置及远程SSH
  • ¥15 怎么让点阵屏显示静态爱心,用keiluVision5写出让点阵屏显示静态爱心的代码,越快越好
  • ¥15 PSPICE制作一个加法器
  • ¥15 javaweb项目无法正常跳转
  • ¥15 VMBox虚拟机无法访问
  • ¥15 skd显示找不到头文件
  • ¥15 机器视觉中图片中长度与真实长度的关系
  • ¥15 fastreport table 怎么只让每页的最下面和最顶部有横线
  • ¥15 java 的protected权限 ,问题在注释里
  • ¥15 这个是哪里有问题啊?