Tipos de cursor (controlador SQLSRV)
El controlador SQLSRV permite crear un conjunto de resultados con filas a las que se puede acceder en cualquier orden según el tipo de cursor. En este tema se explican los cursores del lado cliente (almacenados en búfer) y del lado servidor (no almacenados en búfer).
Tipos de cursor
Cuando se crea un conjunto de resultados con sqlsrv_query o con sqlsrv_prepare, se puede especificar el tipo de cursor. De forma predeterminada, se usa un cursor de solo avance, que permite desplazar una fila cada vez comenzando en la primera fila del conjunto de resultados hasta llegar al final.
Puede crear un conjunto de resultados con un cursor desplazable, que le permite tener acceso a cualquier fila del conjunto de resultados, en cualquier orden. En la tabla siguiente se muestran los valores que se pueden pasar a la opción Scrollable en sqlsrv_query o sqlsrv_prepare.
Opción | Descripción |
---|---|
SQLSRV_CURSOR_FORWARD | Permite desplazar una fila cada vez comenzando en la primera fila del conjunto de resultados hasta llegar al final. Este es el tipo de cursor predeterminado. sqlsrv_num_rows devuelve un error para los conjuntos de resultados creados con este tipo de cursor. forward es la forma abreviada de SQLSRV_CURSOR_FORWARD. |
SQLSRV_CURSOR_STATIC | Permite acceder a las filas en cualquier orden, pero no reflejará los cambios en la base de datos. static es la forma abreviada de SQLSRV_CURSOR_STATIC. |
SQLSRV_CURSOR_DYNAMIC | Permite acceder a las filas en cualquier orden y reflejará los cambios en la base de datos. sqlsrv_num_rows devuelve un error para los conjuntos de resultados creados con este tipo de cursor. dynamic es la forma abreviada de SQLSRV_CURSOR_DYNAMIC. |
SQLSRV_CURSOR_KEYSET | Permite acceder a las filas en cualquier orden. Pero los cursores de conjunto de claves no actualizan el recuento de filas si se elimina una fila de la tabla (las filas eliminadas se devuelven sin valores). keyset es la forma abreviada de SQLSRV_CURSOR_KEYSET. |
SQLSRV_CURSOR_CLIENT_BUFFERED | Permite acceder a las filas en cualquier orden. Crea una consulta de cursor del lado cliente. buffered es la forma abreviada de SQLSRV_CURSOR_CLIENT_BUFFERED. |
Si una consulta genera varios conjuntos de resultados, la opción Scrollable se aplica a todos ellos.
Selección de filas en un conjunto de resultados
Después de crear un conjunto de resultados, puede usar sqlsrv_fetch, sqlsrv_fetch_array o sqlsrv_fetch_object para especificar una fila.
En la tabla siguiente se describen los valores que se pueden especificar en el parámetro row.
Parámetro | Descripción |
---|---|
SQLSRV_SCROLL_NEXT | Especifica la siguiente fila. Este es el valor predeterminado si no se especifica el parámetro row para un conjunto de resultados desplazable. |
SQLSRV_SCROLL_PRIOR | Especifica la fila delante de la fila actual. |
SQLSRV_SCROLL_FIRST | Especifica la primera fila del conjunto de resultados. |
SQLSRV_SCROLL_LAST | Especifica la última fila del conjunto de resultados. |
SQLSRV_SCROLL_ABSOLUTE | Indica la fila especificada con el parámetro offset. |
SQLSRV_SCROLL_RELATIVE | Indica la fila especificada con parámetro offset de la fila actual. |
Cursores del lado servidor y el controlador SQLSRV
En el ejemplo siguiente se muestra el efecto de los distintos cursores. En la línea 33 del ejemplo, verá la primera de tres instrucciones de consulta que especifican cursores diferentes. Dos de las instrucciones de consulta están comentadas. Cada vez que ejecute el programa, use un tipo de cursor diferente para ver el efecto de la actualización de la base de datos en la línea 47.
<?php
$server = "server_name";
$conn = sqlsrv_connect( $server, array( 'Database' => 'test' ));
if ( $conn === false ) {
die( print_r( sqlsrv_errors(), true ));
}
$stmt = sqlsrv_query( $conn, "DROP TABLE dbo.ScrollTest" );
if ( $stmt !== false ) {
sqlsrv_free_stmt( $stmt );
}
$stmt = sqlsrv_query( $conn, "CREATE TABLE ScrollTest (id int, value char(10))" );
if ( $stmt === false ) {
die( print_r( sqlsrv_errors(), true ));
}
$stmt = sqlsrv_query( $conn, "INSERT INTO ScrollTest (id, value) VALUES(?,?)", array( 1, "Row 1" ));
if ( $stmt === false ) {
die( print_r( sqlsrv_errors(), true ));
}
$stmt = sqlsrv_query( $conn, "INSERT INTO ScrollTest (id, value) VALUES(?,?)", array( 2, "Row 2" ));
if ( $stmt === false ) {
die( print_r( sqlsrv_errors(), true ));
}
$stmt = sqlsrv_query( $conn, "INSERT INTO ScrollTest (id, value) VALUES(?,?)", array( 3, "Row 3" ));
if ( $stmt === false ) {
die( print_r( sqlsrv_errors(), true ));
}
$stmt = sqlsrv_query( $conn, "SELECT * FROM ScrollTest", array(), array( "Scrollable" => 'keyset' ));
// $stmt = sqlsrv_query( $conn, "SELECT * FROM ScrollTest", array(), array( "Scrollable" => 'dynamic' ));
// $stmt = sqlsrv_query( $conn, "SELECT * FROM ScrollTest", array(), array( "Scrollable" => 'static' ));
$rows = sqlsrv_has_rows( $stmt );
if ( $rows != true ) {
die( "Should have rows" );
}
$result = sqlsrv_fetch( $stmt, SQLSRV_SCROLL_LAST );
$field1 = sqlsrv_get_field( $stmt, 0 );
$field2 = sqlsrv_get_field( $stmt, 1 );
echo "\n$field1 $field2\n";
$stmt2 = sqlsrv_query( $conn, "delete from ScrollTest where id = 3" );
// or
// $stmt2 = sqlsrv_query( $conn, "UPDATE ScrollTest SET id = 4 WHERE id = 3" );
if ( $stmt2 !== false ) {
sqlsrv_free_stmt( $stmt2 );
}
$result = sqlsrv_fetch( $stmt, SQLSRV_SCROLL_LAST );
$field1 = sqlsrv_get_field( $stmt, 0 );
$field2 = sqlsrv_get_field( $stmt, 1 );
echo "\n$field1 $field2\n";
sqlsrv_free_stmt( $stmt );
sqlsrv_close( $conn );
?>
Cursores del lado cliente y el controlador SQLSRV
Los cursores del lado cliente son una característica agregada a la versión 3.0 de Controladores de Microsoft para PHP para SQL Server que permite almacenar en caché un conjunto de resultados completo en memoria. El recuento de filas está disponible después de ejecutar la consulta cuando se usa un cursor del lado cliente.
Los cursores del lado cliente deben usarse para conjuntos de resultados de tamaño pequeño a mediano. Con conjuntos de resultados grandes se deben usar cursores del lado servidor.
Una consulta devolverá False si el búfer no es lo suficientemente grande como para contener todo el conjunto de resultados. Puede aumentar el tamaño del búfer hasta el límite de memoria PHP.
Con el controlador SQLSRV, puede configurar el tamaño del búfer que contiene el conjunto de resultados con el valor ClientBufferMaxKBSize de sqlsrv_configure. sqlsrv_get_config devuelve el valor de ClientBufferMaxKBSize. También puede establecer el tamaño máximo del búfer en el archivo php.ini con sqlsrv.ClientBufferMaxKBSize (por ejemplo, sqlsrv.ClientBufferMaxKBSize = 1024).
El ejemplo siguiente muestra:
El recuento de filas siempre está disponible con un cursor del lado cliente.
Uso de cursores del lado cliente e instrucciones por lotes.
<?php
$serverName = "(local)";
$connectionInfo = array("Database"=>"AdventureWorks");
$conn = sqlsrv_connect( $serverName, $connectionInfo);
if ( $conn === false ) {
echo "Could not connect.\n";
die( print_r( sqlsrv_errors(), true));
}
$tsql = "select * from HumanResources.Department";
// Execute the query with client-side cursor.
$stmt = sqlsrv_query($conn, $tsql, array(), array("Scrollable"=>"buffered"));
if (! $stmt) {
echo "Error in statement execution.\n";
die( print_r( sqlsrv_errors(), true));
}
// row count is always available with a client-side cursor
$row_count = sqlsrv_num_rows( $stmt );
echo "\nRow count = $row_count\n";
// Move to a specific row in the result set.
$row = sqlsrv_fetch($stmt, SQLSRV_SCROLL_FIRST);
$EmployeeID = sqlsrv_get_field( $stmt, 0);
echo "Employee ID = $EmployeeID \n";
// Client-side cursor and batch statements
$tsql = "select top 2 * from HumanResources.Employee;Select top 3 * from HumanResources.EmployeeAddress";
$stmt = sqlsrv_query($conn, $tsql, array(), array("Scrollable"=>"buffered"));
if (! $stmt) {
echo "Error in statement execution.\n";
die( print_r( sqlsrv_errors(), true));
}
$row_count = sqlsrv_num_rows( $stmt );
echo "\nRow count for first result set = $row_count\n";
$row = sqlsrv_fetch($stmt, SQLSRV_SCROLL_FIRST);
$EmployeeID = sqlsrv_get_field( $stmt, 0);
echo "Employee ID = $EmployeeID \n";
sqlsrv_next_result($stmt);
$row_count = sqlsrv_num_rows( $stmt );
echo "\nRow count for second result set = $row_count\n";
$row = sqlsrv_fetch($stmt, SQLSRV_SCROLL_LAST);
$EmployeeID = sqlsrv_get_field( $stmt, 0);
echo "Employee ID = $EmployeeID \n";
?>
En el ejemplo siguiente se muestra un cursor del lado cliente mediante sqlsrv_prepare y un tamaño de búfer de cliente diferente.
<?php
$serverName = "(local)";
$connectionInfo = array( "Database"=>"AdventureWorks");
$conn = sqlsrv_connect( $serverName, $connectionInfo);
if ( $conn === false ) {
echo "Could not connect.\n";
die( print_r( sqlsrv_errors(), true));
}
$tsql = "select * from HumanResources.Employee";
$stmt = sqlsrv_prepare( $conn, $tsql, array(), array("Scrollable" => SQLSRV_CURSOR_CLIENT_BUFFERED, "ClientBufferMaxKBSize" => 51200));
if (! $stmt ) {
echo "Statement could not be prepared.\n";
die( print_r( sqlsrv_errors(), true));
}
sqlsrv_execute( $stmt);
$row_count = sqlsrv_num_rows( $stmt );
if ($row_count)
echo "\nRow count = $row_count\n";
$row = sqlsrv_fetch($stmt, SQLSRV_SCROLL_FIRST);
if ($row ) {
$EmployeeID = sqlsrv_get_field( $stmt, 0);
echo "Employee ID = $EmployeeID \n";
}
?>