使用游标进行PHP SQLSRV查询的方法与注意事项
作者:cncco 发布时间:2023-05-22 10:51:10
SQLSRV驱动程序允许您创建一个结果集,其中包含可以根据游标类型以任何顺序访问的行。本主题将讨论客户端(缓冲)和服务器端(非缓冲)游标及其用法。
使用SQLSRV查询时,默认情况下,使用向前游标,它允许您从结果集的第一行开始一次移动一行,直到到达结果集的末尾。当然,有时这不是你所期待的,这就需要指定游标类型。
游标类型
您可以使用Scrollable来指定结果集的游标,以实现各种以顺序访问结果集中的任何行。下表列出了可以传递给Scrollable的选项。
Option | Description |
---|---|
SQLSRV_CURSOR_FORWARD | 允许您从结果集的第一行开始一次移动一行,直到到达结果集的末尾。 这是默认的游标类型。 sqlsrv_num_rows将返回一个错误。 forward;是SQLSRV_CURSOR_FORWARD的缩写形式。 |
SQLSRV_CURSOR_STATIC | 允许您以任何顺序访问行,但不会反映数据库中的更改。 static;是SQLSRV_CURSOR_STATIC的缩写形式。 |
SQLSRV_CURSOR_DYNAMIC | 允许您以任何顺序访问行,并反映数据库中的更改。 sqlsrv_num_rows将返回一个错误。 dynamic;是SQLSRV_CURSOR_DYNAMIC的缩写形式。 |
SQLSRV_CURSOR_KEYSET | 允许您以任何顺序访问行。但是,如果从表中删除了一行,键集游标不会更新行计数(删除的行返回时没有值)。 keyset;是SQLSRV_CURSOR_KEYSET的缩写形式。 |
SQLSRV_CURSOR_CLIENT_BUFFERED | 允许您以任何顺序访问行。创建客户端游标查询。 buffered;是SQLSRV_CURSOR_CLIENT_BUFFERED的缩写形式。 |
如果查询生成多个结果集,则Scrollable选项应用于所有结果集。
选择结果集中的行
创建结果集后,就可以使用sqlsrv_fetch、sqlsrv_fetch_array或sqlsrv_fetch_object来指定行了。
下表说明了可以对行进行的操作。
参数 | 描述 |
---|---|
SQLSRV_SCROLL_NEXT | 指定下一行。 |
SQLSRV_SCROLL_PRIOR | 指定当前行之前的行。 |
SQLSRV_SCROLL_FIRST | 指定结果集中的第一行。 |
SQLSRV_SCROLL_LAST | 指定结果集中的最后一行。 |
SQLSRV_SCROLL_ABSOLUTE | 指定指定的行抵消参数。 |
SQLSRV_SCROLL_RELATIVE | 指定指定的行抵消当前行中的参数。 |
SQLSRV Driver之服务端游标
以下示例显示了各种游标的效果。在示例的第33行,您可以看到指定不同游标的三条查询语句中的第一条。其中两个查询语句被注释。每次运行程序时,使用不同的游标类型查看第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 );
?>
SQLSRV Driver之客户端游标
客户端游标是Microsoft Drivers for PHP for SQL Server 3.0版中添加的一项功能,它允许您在内存中缓存整个结果集。使用客户端游标执行查询后,行计数可用。
客户端游标应该用于中小型结果集。对大型结果集使用服务器端游标。
如果缓冲区不够大,无法容纳整个结果集,则查询将返回false。您可以将缓冲区大小增加到PHP内存限制。
使用SQLSRV驱动程序,可以使用sqlsrv_configure来设置ClientBufferMaxKBSize以配置保存结果集的缓冲区的大小。
sqlsrv_get_config返回ClientBufferMaxKBSize的值。
您还可以在php.ini文件中使用sqlsrv.ClientBufferMaxKBSize来设置最大缓冲区大小(例如,sqlsrv.clientBufferMaxKBSign=1024)。
以下示例显示:
1、行计数始终可用于客户端游标。
2、使用客户端游标和批处理语句。
<?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(sqlsrv_prepare)并配置了不同的客户端缓冲区大小。
<?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";
}
?>
来源:https://blog.csdn.net/cncco/article/details/130538450


猜你喜欢
- 前几天帮人调试一个ASP+SQL2000+IIS5.1/6.0的网站程序,调试过程中遇到的问题如下:一、 SQLServer登录 原先存在备
- 参数Parameters解析响应时间resolveTimeout 数据类型:长整型。简单地说就是程序对目标主机的名字解析解析的一个过程时间。
- 一、中间键的引入:Django中间件(Middleware)是一个 轻量级、底层的 “插件”系 统,可以介入 Django的请求和响应处理过
- 场景需求 使用OpenCV,往往遇到这类场景:需要清除目标图像中比较小的噪声区,保留主要
- 1、效果图2、安装npm install --save nprogress基本用法NProgress.start();NProgress.d
- 遇到问题nohup python flush.py &这样运行,生成了nohup.out文件,但是内容始终是空的,试了半天也不行。浪
- 本文实例讲述了JavaScript观察者模式(publish/subscribe)原理与实现方法。分享给大家供大家参考,具体如下:观察者模式
- 本文实例讲述了python实现unicode转中文及转换默认编码的方法。分享给大家供大家参考,具体如下:一、在爬虫抓取网页信息时常需要将类似
- 本文实例讲述了Go语言执行系统命令行命令的方法。分享给大家供大家参考。具体如下:执行Go代码时可以附加参数,包括要执行的命令和给命令的参数p
- 在使用lepus3.7监控MySQL数据库的时候,碰到了以下几个问题,本博客给出了这些问题产生的原因,以及相应的解决办法。1. 问
- 前言最近参加了大创项目,题目涉及到计算机视觉,学姐发了个修正图像的博客链接,于是打算用这个题目入门OpenCV。分析问题照片中的PPT区域总
- 前言在前程无忧上投递简历发现有竞争力分析,免费能看到匹配度评价和综合竞争力分数,可以做投递参考计算方式综合竞争力得分应该越高越好,匹配度评语
- 原因: __str__()这个特殊方法将对象转换为字符串的结果效果图:代码:# 定义一个Person类class Person(o
- 本文实例讲述了PHP面向对象程序设计子类扩展父类(子类重新载入父类)操作。分享给大家供大家参考,具体如下:在PHP中,会遇到这样的情况,子类
- 本节为大家分享的例子是wxpython Frame的用法。例子:#!/usr/bin/python # -*- coding:
- 协程的定义协程(Coroutine),又称微线程,纤程。(协程是一种用户态的轻量级线程)作用:在执行 A 函数的时候,可以随时中断,去执行
- 首先 你要有个女朋友效果:需要安装几个包pip install wxpypip install wechat_senderpip insta
- 本文实例讲述了python获取文件扩展名的方法。分享给大家供大家参考。具体实现方法如下:import os.path def file_ex
- 保证只能运行一个脚本实例,方法是程序运行时监听一个特定端口,如果失败则说明已经有实例在跑。使用装饰器实现,便于重用import functo
- 实际中,很多数据都是存为txt文件、csv文件等,但是在程序中处理的时候numpy数组或列表是最方便的。本文简单介绍读入txt文件以及将之转