PHP 8.3.4 Released!

PDOStatement::closeCursor

(PHP 5 >= 5.1.0, PHP 7, PHP 8, PECL pdo >= 0.9.0)

PDOStatement::closeCursor カーソルを閉じてステートメントを再実行できるようにする

説明

public PDOStatement::closeCursor(): bool

PDOStatement::closeCursor() は、 他の SQL ステートメントを発行できるようにサーバーへの接続を解放しますが、 ステートメントは再実行可能な状態のまま残されます。

このメソッドは以前に実行された PDOStatement オブジェクトが行をまだフェッチしていない場合に PDOStatement オブジェクトの実行をサポートしていないデータベースドライバに対して有用です。 もし使用しているデータベースドライバがこの制限を受ける場合、 out-of-sequence エラーが出力されます。

PDOStatement::closeCursor() は、 オプションのドライバ固有のメソッド (最大の効率を得るため) もしくはドライバ固有の関数がインストールされていない場合の汎用的な PDO フォールバックとして実装されています。 汎用的な PDO フォールバックは、PHP スクリプト中に以下のようなコードを書くことと意味的に等価です。

<?php
do {
while (
$stmt->fetch())
;
if (!
$stmt->nextRowset())
break;
} while (
true);
?>

パラメータ

この関数にはパラメータはありません。

戻り値

成功した場合に true を、失敗した場合に false を返します。

エラー / 例外

PDO::ATTR_ERRMODEPDO::ERRMODE_WARNING に設定されていた場合、E_WARNING レベルのエラーが発生します。

PDO::ATTR_ERRMODEPDO::ERRMODE_EXCEPTION に設定されていた場合、PDOException がスローされます。

例1 PDOStatement::closeCursor() の例

以下の例では、PDOStatement オブジェクト $stmt は複数の行を返しますが、このアプリケーションは先頭行のみフェッチし、 PDOStatement オブジェクトをフェッチしていない行がある状態のままにします。 このアプリケーションがが全てのデータベースドライバで動作するよう、 PDOStatement オブジェクト $otherStmt を実行する前に $stmt に対して PDOStatement::closeCursor() の呼び出しを挿入しています。

<?php
/* PDOStatement オブジェクトを生成する */
$stmt = $dbh->prepare('SELECT foo FROM bar');

/* 第二の PDOStatement オブジェクトを生成する */
$otherStmt = $dbh->prepare('SELECT foobaz FROM foobar');

/* 最初の文を実行する */
$stmt->execute();

/* 結果から先頭行のみフェッチする */
$stmt->fetch();

/* 続く closeCursor() のコールはいくつかのドライバでは必要となる */
$stmt->closeCursor();

/* ここで第二の文を実行することができる */
$otherStmt->execute();
?>

参考

add a note

User Contributed Notes 4 notes

up
2
Anonymous
8 years ago
In case this is helpful to anybody else who ends-up here after getting the following error:

SQLState: 24000 [Microsoft][ODBC SQL Server Driver]Invalid cursor state

PDOStatement :: closeCursor() did not fix the issue for me. However, adding SET NOCOUNT ON to the beginning of my stored procedure did.
up
-7
jhill9693 at gmail dot com
12 years ago
If you ran a SQL statement (vs a query that returns data) such as UPDATE, try unsetting your PDOStatement object instead of calling PDOStatement::closeCursor().
up
-9
Anonymous
8 years ago
At least with MySQL this function also resets any bound columns, so the fetches will go through as expected but you will be getting stale data in the loop.

Redo all the binds before continuing!
up
-12
narada dot sage at googlemail dot com
17 years ago
When running multiple queries one after another especially when stored procedures are involved one must release all result sets and fetch all rows in each result set for a stored procedure before moving onto the next query. This is important because a stored procedure returns an extra (empty) result set as a result of having called the procedure itself.

In my case calling PDOStatement :: closeCursor() did not work (on php-5.1.3-rc2) and I was presented with the following error message: "SQLSTATE[HY000]: General error: 2013 Lost connection to MySQL server during query" upon trying to PDO :: prepare() my second query. So I used the following drop in replacement within one of my classes which fixed the issue.

<?php
/**
* @param PDOStatement $oStm
*/
public static function closeCursor($oStm) {
do
$oStm->fetchAll();
while (
$oStm->nextRowSet());
}
?>
To Top