PHP PDOStatement::closeCursor 方法
最后修改于 2025 年 4 月 19 日
PDOStatement::closeCursor 方法释放与服务器的连接。这允许在当前语句仍有未获取的行时执行其他 SQL 语句。
基本定义
PDOStatement::closeCursor 清空 PDOStatement 对象的语句集。当您在完成当前语句集之前需要执行另一个查询时,这非常有用。
语法:public PDOStatement::closeCursor(): bool。该方法成功时返回 true,失败时返回 false。对于不支持多个活动语句的数据库来说,这一点尤为重要。
基本用法
这显示了 closeCursor 的最简单用法,即释放数据库资源。
<?php
declare(strict_types=1);
try {
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
$stmt = $pdo->query('SELECT * FROM large_table');
// Process some rows
for ($i = 0; $i < 10; $i++) {
$row = $stmt->fetch();
echo "Row {$i}: {$row['id']}\n";
}
// Free up the connection
$stmt->closeCursor();
// Execute another query
$pdo->query('UPDATE stats SET processed = 1');
} catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
此示例从一个大型语句集中获取 10 行,然后调用 closeCursor。这使得后续的 UPDATE 查询可以在不等待所有行被获取的情况下执行。
多个语句
演示了在同一连接上执行多个语句时使用 closeCursor。
<?php
declare(strict_types=1);
try {
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
// First query
$stmt1 = $pdo->query('SELECT * FROM users WHERE active = 1');
while ($user = $stmt1->fetch()) {
echo "Active user: {$user['name']}\n";
}
$stmt1->closeCursor();
// Second query
$stmt2 = $pdo->query('SELECT * FROM products WHERE stock < 10');
while ($product = $stmt2->fetch()) {
echo "Low stock: {$product['name']}\n";
}
$stmt2->closeCursor();
} catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
这显示了两个查询之间的正确资源清理。在处理下一个语句之前,会先关闭每个语句。这可以防止 MySQL 中可能出现的“命令不同步”错误。
带有未获取结果
展示了在未获取所有结果的情况下如何使用 closeCursor。
<?php
declare(strict_types=1);
try {
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
$stmt = $pdo->query('SELECT * FROM large_dataset');
// Only process first 100 rows
$count = 0;
while ($row = $stmt->fetch() && $count++ < 100) {
processRow($row);
}
// Close cursor even though more rows exist
$stmt->closeCursor();
// Execute another query
$pdo->exec('DELETE FROM temp_data');
} catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
function processRow($row) {
// Process row data
}
这里我们故意不获取语句集中的所有行。在执行另一个语句之前调用 closeCursor 来释放资源。这可以防止大型语句集出现内存泄漏。
在事务中
演示了在数据库事务中使用 closeCursor。
<?php
declare(strict_types=1);
try {
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
$pdo->beginTransaction();
// First operation
$stmt1 = $pdo->query('SELECT * FROM accounts WHERE balance > 1000');
$richAccounts = $stmt1->fetchAll();
$stmt1->closeCursor();
// Second operation
$stmt2 = $pdo->prepare('UPDATE accounts SET flagged = 1 WHERE id = ?');
foreach ($richAccounts as $account) {
$stmt2->execute([$account['id']]);
}
$pdo->commit();
} catch (PDOException $e) {
$pdo->rollBack();
echo "Error: " . $e->getMessage();
}
此示例显示了事务中正确的游标管理。在处理结果和执行更新之前,会先关闭第一个查询的游标。这可以保持事务边界的清晰。
带有预准备语句
展示了在多次执行的预准备语句中使用 closeCursor 的用法。
<?php
declare(strict_types=1);
try {
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
$stmt = $pdo->prepare('SELECT * FROM orders WHERE customer_id = ?');
$customerIds = [5, 8, 12];
foreach ($customerIds as $id) {
$stmt->execute([$id]);
$orders = $stmt->fetchAll();
processOrders($orders);
$stmt->closeCursor();
}
} catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
function processOrders($orders) {
// Process customer orders
}
这演示了在重用预准备语句时正确的游标清理。每次执行和处理完结果后,都会调用 closeCursor 来重置语句以供下次执行。
错误处理
展示了如何处理使用 closeCursor 时的错误。
<?php
declare(strict_types=1);
try {
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
$stmt = $pdo->query('SELECT * FROM products');
// Process some rows
while ($row = $stmt->fetch()) {
echo "Product: {$row['name']}\n";
}
// Attempt to close cursor
if (!$stmt->closeCursor()) {
throw new Exception('Failed to close cursor');
}
// Execute another query
$pdo->exec('UPDATE inventory SET checked = NOW()');
} catch (PDOException $e) {
echo "Database error: " . $e->getMessage();
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}
此示例检查 closeCursor 的返回值,如果失败则抛出异常。正确的错误处理可确保您了解任何游标清理问题。
带有存储过程
演示了调用返回多个结果集的存储过程时使用 closeCursor 的用法。
<?php
declare(strict_types=1);
try {
$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
$stmt = $pdo->query('CALL get_sales_report()');
// Process first result set
echo "Daily Sales:\n";
while ($row = $stmt->fetch()) {
echo "{$row['day']}: {$row['amount']}\n";
}
$stmt->closeCursor();
// Move to next result set
if ($stmt->nextRowset()) {
echo "\nMonthly Sales:\n";
while ($row = $stmt->fetch()) {
echo "{$row['month']}: {$row['amount']}\n";
}
}
$stmt->closeCursor();
} catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
这显示了如何正确管理返回多个结果集的存储过程的游标。在处理每个结果集之间调用 closeCursor 以确保过渡的清晰。
最佳实践
- 始终使用:完成语句集后调用 closeCursor。
- 在新查询之前:先清理之前的语句。
- 对于大型结果:对内存管理至关重要。
- 在循环中:重用语句时关闭游标。
- 错误处理:检查返回值以发现问题。
来源
PHP PDOStatement::closeCursor 文档
本教程通过实际示例涵盖了 PDOStatement::closeCursor 方法,并展示了其在数据库操作中的重要性。
作者
列出 所有 PHP PDO 函数。