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 函数。