CakeFest 2024: The Official CakePHP Conference

PDOStatement::closeCursor

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

PDOStatement::closeCursor Cierra un cursor, habilitando a la sentencia para que sea ejecutada otra vez

Descripción

public PDOStatement::closeCursor(): bool

PDOStatement::closeCursor() libera la conexión al servidor, por lo que otras sentencias SQL podrían ejecutarse, pero deja la sentencia en un estado que la habilita para ser ejecutada otra vez.

Este método es útil para los controladores de bases de datos que no admiten la ejecución de un objeto PDOStatement cuando otro objeto PDOStatement previamente ejecutado aún le restan filas por obtener. Si su controlador de bases de datos tiene esta limitación, el problema podría manifestarse en un error de "fuera de sencuencia".

PDOStatement::closeCursor() está implementado como un método opcional específico del controlador (permitienedo la máxima eficiencia), o como la alternativa genérica de PDO si no está instalada ninguna función específica del controlador. La alternativa genérica de PDO es semánticamente la misma que si se escribiera el siguiente código en un script de PHP:

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

Valores devueltos

Devuelve true en caso de éxito o false en caso de error.

Ejemplos

Ejemplo #1 Un ejemplo de PDOStatement::closeCursor()

En el siguiente ejemplo, el objeto PDOStatement $sentencia devuelve múltiples filas, aunque la aplicación solamente obtenga la primera, dejando al objeto PDOStatement con filas aún por obtener. Para asegurarse de que la aplicación funcionará con todos los controladores de bases de datos, el autor inserta una llmada a PDOStatement::closeCursor() sobre $sentencia antes de ejecutar el objeto PDOStatement $otraSentencia.

<?php
/* Crear un objeto PDOStatement */
$sentencia = $gbd->prepare('SELECT foo FROM bar');

/* Crear un segundo objeto PDOStatement */
$otraSentencia = $gbd->prepare('SELECT foobaz FROM foobar');

/* Ejecutar la primera sentencia */
$sentencia->execute();

/* Obtener solamente la primera fila de los resultados */
$sentencia->fetch();

/* La siguiente llamada a closeCursor() podría ser necesaria para algunos controladores */
$sentencia->closeCursor();

/* Ahora se puede ejecutar la segunda sentencia */
$otraSentencia->execute();
?>

Ver también

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