Типы курсоров (драйвер SQLSRV)Cursor Types (SQLSRV Driver)

СкачатьСкачать драйвер PHPDownloadDownload PHP Driver

Драйвер SQLSRV позволяет создать результирующий набор со строками, доступ к которым можно осуществлять в любом порядке в зависимости от типа курсора.The SQLSRV driver lets you create a result set with rows that you can access in any order, depending on the cursor type. В этой статье рассматриваются клиентские (в буфере) и серверные курсоры (без буферизации).This topic will discuss client-side (buffered) and server-side (unbuffered) cursors.

Типы курсоровCursor Types

При создании результирующего набора с помощью sqlsrv_query или sqlsrv_prepare можно указать тип курсора.When you create a result set with sqlsrv_query or with sqlsrv_prepare, you can specify the type of cursor. По умолчанию используется курсор последовательного доступа, который позволяет переместить одну строку за раз, начиная с первой строки результирующего набора и до его конца.By default, a forward-only cursor is used, which lets you move one row at a time starting at the first row of the result set until you reach the end of the result set.

Можно создать результирующий набор с прокручиваемым курсором, который позволяет получить доступ к любой строке в результирующем наборе в любом порядке.You can create a result set with a scrollable cursor, which allows you to access any row in the result set, in any order. В следующей таблице перечислены значения, которые можно передать в параметре Scrollable в sqlsrv_query или sqlsrv_prepare.The following table lists the values that can be passed to the Scrollable option in sqlsrv_query or sqlsrv_prepare.

ПараметрOption ОписаниеDescription
SQLSRV_CURSOR_FORWARDSQLSRV_CURSOR_FORWARD Позволяет переместить одну строку за раз, начиная с первой строки результирующего набора и до его конца.Lets you move one row at a time starting at the first row of the result set until you reach the end of the result set.

Это тип курсора по умолчанию.This is the default cursor type.

sqlsrv_num_rows возвращает ошибку для результирующих наборов, созданных с этим типом курсора.sqlsrv_num_rows returns an error for result sets created with this cursor type.

forward является сокращенной формой SQLSRV_CURSOR_FORWARD.forward is the abbreviated form of SQLSRV_CURSOR_FORWARD.
SQLSRV_CURSOR_STATICSQLSRV_CURSOR_STATIC Позволяет получать доступ к строкам в любом порядке, но не отражает изменения в базе данных.Lets you access rows in any order but will not reflect changes in the database.

static является сокращенной формой SQLSRV_CURSOR_STATIC.static is the abbreviated form of SQLSRV_CURSOR_STATIC.
SQLSRV_CURSOR_DYNAMICSQLSRV_CURSOR_DYNAMIC Позволяет получать доступ к строкам в любом порядке и будет отражать изменения в базе данных.Lets you access rows in any order and will reflect changes in the database.

sqlsrv_num_rows возвращает ошибку для результирующих наборов, созданных с этим типом курсора.sqlsrv_num_rows returns an error for result sets created with this cursor type.

dynamic является сокращенной формой SQLSRV_CURSOR_DYNAMIC.dynamic is the abbreviated form of SQLSRV_CURSOR_DYNAMIC.
SQLSRV_CURSOR_KEYSETSQLSRV_CURSOR_KEYSET Позволяет получать доступ к строкам в любом порядке.Lets you access rows in any order. Однако курсор набора ключей не обновляет количество строк, если строка удаляется из таблицы (удаленная строка возвращается без значений).However, a keyset cursor does not update the row count if a row is deleted from the table (a deleted row is returned with no values).

keyset является сокращенной формой SQLSRV_CURSOR_KEYSET.keyset is the abbreviated form of SQLSRV_CURSOR_KEYSET.
SQLSRV_CURSOR_CLIENT_BUFFEREDSQLSRV_CURSOR_CLIENT_BUFFERED Позволяет получать доступ к строкам в любом порядке.Lets you access rows in any order. Создает запрос курсора на стороне клиента.Creates a client-side cursor query.

buffered является сокращенной формой SQLSRV_CURSOR_CLIENT_BUFFERED.buffered is the abbreviated form of SQLSRV_CURSOR_CLIENT_BUFFERED.

Если запрос формирует несколько результирующих наборов, параметр Scrollable применяется ко всем результирующим наборам.If a query generates multiple result sets, the Scrollable option applies to all result sets.

Выбор строк в результирующем набореSelecting Rows in a Result Set

После создания результирующего набора можно использовать sqlsrv_fetch, sqlsrv_fetch_array или sqlsrv_fetch_object, чтобы указать строку.After you create a result set, you can use sqlsrv_fetch, sqlsrv_fetch_array, or sqlsrv_fetch_object to specify a row.

В следующей таблице описаны значения, которые можно указать в параметре row.The following table describes the values you can specify in the row parameter.

ПараметрParameter ОписаниеDescription
SQLSRV_SCROLL_NEXTSQLSRV_SCROLL_NEXT Задает следующую строку.Specifies the next row. Это значение по умолчанию, если параметр row для прокручиваемого набора результатов не указан.This is the default value, if you do not specify the row parameter for a scrollable result set.
SQLSRV_SCROLL_PRIORSQLSRV_SCROLL_PRIOR Указывает строку перед текущей строкой.Specifies the row before the current row.
SQLSRV_SCROLL_FIRSTSQLSRV_SCROLL_FIRST Указывает первую строку в результирующем наборе.Specifies the first row in the result set.
SQLSRV_SCROLL_LASTSQLSRV_SCROLL_LAST Указывает последнюю строку в результирующем наборе.Specifies the last row in the result set.
SQLSRV_SCROLL_ABSOLUTESQLSRV_SCROLL_ABSOLUTE Указывает строку, заданную в параметре offset.Specifies the row specified with the offset parameter.
SQLSRV_SCROLL_RELATIVESQLSRV_SCROLL_RELATIVE Указывает строку, заданную в параметре offset из текущей строки.Specifies the row specified with the offset parameter from the current row.

Курсоры на стороне сервера и драйвер SQLSRVServer-Side Cursors and the SQLSRV Driver

В следующем примере показано воздействие различных курсоров.The following example shows the effect of the various cursors. В строке 33 в примере показаны первые три оператора запроса, указывающие разные курсоры.On line 33 of the example, you see the first of three query statements that specify different cursors. Два оператора запроса имеют комментарии.Two of the query statements are commented. Каждый раз при запуске программы используйте другой тип курсора, чтобы увидеть результат обновления базы данных в строке 47.Each time you run the program, use a different cursor type to see the effect of the database update on line 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 );  
?>  

Курсоры на стороне клиента и драйвер SQLSRVClient-Side Cursors and the SQLSRV Driver

Курсоры на стороне клиента были добавлены как функция в Драйверы Microsoft SQL Server для PHPMicrosoft Drivers for PHP for SQL Server версии 3.0. Они позволяют кэшировать в памяти весь результирующий набор.Client-side cursors are a feature added in version 3.0 of the Драйверы Microsoft SQL Server для PHPMicrosoft Drivers for PHP for SQL Server that allows you to cache an entire result set in memory. Число строк доступно после выполнения запроса при использовании курсора на стороне клиента.Row count is available after the query is executed when using a client-side cursor.

Курсоры на стороне клиента следует использовать только для малых и средних результирующих наборов.Client-side cursors should be used for small- to medium-sized result sets. Используйте курсоры на стороне сервера для больших результирующих наборов.Use server-side cursors for large result sets.

Запрос возвратит значение false, если буфер недостаточно большой для хранения всего результирующего набора.A query will return false if the buffer is not large enough to hold the entire result set. Вы можете увеличить размер этого буфера вплоть до максимального объема памяти PHP.You can increase the buffer size up to the PHP memory limit.

С помощью драйвера SQLSRV можно настроить размер буфера, содержащего результирующий набор. Для этого нужно задать параметр ClientBufferMaxKBSize для sqlsrv_configure.Using the SQLSRV driver, you can configure the size of the buffer that holds the result set with the ClientBufferMaxKBSize setting for sqlsrv_configure. sqlsrv_get_config возвращает значение ClientBufferMaxKBSize.sqlsrv_get_config returns the value of ClientBufferMaxKBSize. Можно также задать максимальный размер буфера в файле php.ini с помощью sqlsrv.ClientBufferMaxKBSize (например, sqlsrv.ClientBufferMaxKBSize = 1024).You can also set the maximum buffer size in the php.ini file with sqlsrv.ClientBufferMaxKBSize (for example, sqlsrv.ClientBufferMaxKBSize = 1024).

В примере ниже используется следующее:The following sample shows:

  • число строк всегда доступно для курсора на стороне клиента;Row count is always available with a client-side cursor.

  • использование курсоров на стороне клиента и пакетных операторов.Use of client-side cursors and batch statements.

<?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";  
?>  

В следующем примере показан курсор на стороне клиента, использующий sqlsrv_prepare и размер буфера другого клиента.The following sample shows a client-side cursor using sqlsrv_prepare and a different client buffer size.

<?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";  
}  
?>  

См. также:See Also

Указание типа курсора и выбор строкSpecifying a Cursor Type and Selecting Rows