【发布时间】:2015-11-04 23:39:19
【问题描述】:
在以下代码中,事务失败并调用回滚。
但是,就输出而言:
如果我删除 closeCursor(),付款人的余额将打印为 -200$。
如果我指定 closeCursor(),付款人的余额将打印为 0,这是预期的行为。
这是因为第一个 select 语句的结果在第二个运行之前没有被清除。
为什么我们需要关闭连接才能在输出中反映回滚?在这两种情况下,都会调用回滚,因此在 DB 中指定值 0。所以我希望余额打印为 0。
我没有看到关闭连接数据库和获取最新数据库值之间的关系。 Fetch() 从 DB 中获取值,所以如果值为 0,为什么“它认为”它是 -200?
这仅适用于 SQLite。无论您是否使用 closeCursor(),MySQL 都会打印 0。
<?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>
【问题讨论】:
-
closeCursor()不会关闭数据库连接。它重置'prepared'语句并刷新所有未完成的行,以便它可以再次执行。 manual: closecursor. -
感谢您的意见。什么是“杰出行”?回滚导致数据库中的余额值为“0”,那么为什么从连续的SQL查询中获取该值时无法反映该值...?
-
如果您不对查询执行
fetchAll,则有缓冲行等待“获取”。这些在光标关闭时被清除。