PHPCon Poland 2024

PDOStatement::closeCursor

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

PDOStatement::closeCursor Schließt den Cursor, damit die Anweisung erneut ausgeführt werden kann

Beschreibung

public PDOStatement::closeCursor(): bool

PDOStatement::closeCursor() gibt die Verbindung zum Server frei, damit andere SQL-Anweisungen ausgeführt werden können, belässt die Anweisung aber in einem Zustand, in dem sie erneut ausgeführt werden kann.

Diese Methode ist nützlich für Datenbanktreiber, die die Ausführung eines PDOStatement-Objekts nicht unterstützen, wenn ein zuvor ausgeführtes PDOStatement-Objekt noch nicht abgrufene Zeilen enthält. Wenn der Datenbanktreiber diese Einschränkung aufweist, kann es zu einem Out-of-Sequence-Fehler kommen.

PDOStatement::closeCursor() ist entweder als optionale treiberspezifische Methode implementiert (für maximale Effizienz), oder als generischer PDO-Fallback, wenn keine treiberspezifische Funktion installiert ist. Der generische PDO-Fallback ist semantisch dasselbe wie der folgende Code in einem PHP-Skript:

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

Parameter-Liste

Diese Funktion besitzt keine Parameter.

Rückgabewerte

Gibt bei Erfolg true zurück. Bei einem Fehler wird false zurückgegeben.

Fehler/Exceptions

Gibt einen Fehler der Stufe E_WARNING aus, wenn das Attribut PDO::ATTR_ERRMODE auf PDO::ERRMODE_WARNING gesetzt ist.

Löst eine PDOException aus, wenn das Attribut PDO::ATTR_ERRMODE auf PDO::ERRMODE_EXCEPTION gesetzt ist.

Beispiele

Beispiel #1 PDOStatement::closeCursor()-Beispiel

Im folgenden Beispiel gibt das PDOStatement-Objekt $stmt mehrere Zeilen zurück, aber die Anwendung ruft nur die erste Zeile ab, wodurch das PDOStatement-Objekt in einem Zustand mit nicht abgerufenen Zeilen verbleibt. Um sicherzustellen, dass die Anwendung mit allen Datenbanktreibern funktioniert, wird hier PDOStatement::closeCursor() für $stmt aufgerufen, bevor das PDOStatement-Objekt $otherStmt ausgeführt wird.

<?php
/* Erstellen eines PDOStatement-Objekts */
$stmt = $dbh->prepare('SELECT foo FROM bar');

/* Erstellen eines zweiten PDOStatement-Objekts */
$otherStmt = $dbh->prepare('SELECT foobaz FROM foobar');

/* Ausführen der ersten Anweisung */
$stmt->execute();

/* Nur die erste Zeile der Ergebnisse wird abgerufen */
$stmt->fetch();

/* Bei manchen Treibern kann der folgende Aufruf von closeCursor() erforderlich sein */
$stmt->closeCursor();

/* Nun kann die zweite Anweisung ausgeführt werden */
$otherStmt->execute();
?>

Siehe auch

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
13 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
18 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