1、首先什么是游标?

这里引用微软官方的ADO API中的一段话来解释(机器翻译太烂,添加个人翻译)

关系数据库中的操作会对整个行集起作用。 由 SELECT 语句返回的行集包括满足该语句的 WHERE 子句中条件的所有行。 这种由语句返回的完整行集称为结果集。 (对于)应用程序,特别是那些处于交互式并处于联机状态(的应用),并不能总是有效地把整个结果集作为一个单元来使用。 这些应用程序需要一种每次处理一行或一部分行的机制。 游标就是对结果集的一种扩展,(它为应用程序)提供了这种机制。

游标是通过游标库来实现的。游标库是软件,通常作为数据库系统的一部分或数据访问 API来实现,用于管理从数据源 (结果集) 返回的数据的属性。 这些属性包括并发管理、 在结果集中的位置、返回的行数,以及是否可以通过结果集(可滚动性)向前或向后(或两者)移动。

游标会跟踪结果集中的位置,并允许你对结果集逐行执行多个操作,无论是否返回原始表的行。换句话说,游标从概念上讲是返回了基于数据库中表的结果集。 光标这样命名是因为它指示着结果集中的当前位置,就像计算机屏幕上的光标指示当前位置一样。

若要继续了解在 ADO 中其用法的详细信息,熟悉游标的概念很重要。使用游标,你可以:

  • 指定定位在结果集中的特定行。

  • 基于当前的结果集位置的行检索一行或一个行块。

  • 修改结果集中当前位置行中的数据。

  • 向其他用户所做的数据更改定义不同级别的敏感度。

    例如,假设一个应用程序潜在购买者会显示可用产品的列表。 买方滚动列表以查看产品详细信息和成本,并最终选择一个产品进行购买。 对列表的其余部分会出现其他滚动和所选内容。 就关心的是购买者,产品会出现一次,但应用程序使用可滚动游标向上和向下浏览结果集。

记录集的open()方法的原型是这样的:

HRESULT Recordset15::Open ( const _variant_t & Source, const _variant_t & ActiveConnection,enum CursorTypeEnum CursorType, enum LockTypeEnum LockType, long Options )

2、游标类型

CursorTypeEnum
{adOpenUnspecified = -1,adOpenForwardOnly = 0,  adOpenKeyset = 1,       adOpenDynamic = 2,      adOpenStatic = 3
};

(1)静态记录集:当前用户打开记录集后,记录集就保持不变一直到关闭后再次打开它。在这过程中如果数据库中的相应记录发生改变,在当前用户是看不到的。

adOpenForwardOpnly——光标只能向前移动,它仅支持从一开始的行提取到结果集的末尾

adOpenStatic——打开一个静态类型的游标。静态游标始终显示结果集,与光标第一次打开时一样。根据实现,静态游标可以是只读或读/写的,并提供向前和向后滚动。静态游标永远不会检测其他更新、 删除和插入。如果你的应用程序并不需要检测数据改变,而且需要滚动,静态游标是最佳选择。

(2)动态记录集:记录集会实时的反映出数据库中相应记录的更改

adOpenDynamic—— 打开一个完全动态的游标。动态游标可检测对结果集中的行进行的所有更改,而不管这些更改是从光标内部还是由光标外的其他用户发生。所有的 insert、 update 和 delete 语句所做的更改,所有用户都可通过游标可见。动态游标可以检测游标打开后对结果集中的行,顺序和值所做的任何更改。

adOpenKeyset——保持当前记录集的个数不变,它只体现更新操作,不体现删除和添加操作,即只能看到其他用户对记录集数据的更新操作。

3、游标锁定方法

什么是锁定?

锁定是DBMS限制对多用户环境中的行进行访问的过程。 当某行或列以独占的方式锁定时,其他用户将不被允许访问锁定的数据,直到锁定被释放。 这确保了两个用户不能同时更新连续的同一列。

从资源角度来看,锁可能非常昂贵,只有在需要保存数据完整性时才应使用锁。 在数以百计或数千用户可能每秒都试图访问记录的数据库中(如连接到Internet的数据库),不必要的锁定可能会导致应用程序的性能下降。

LockTypeEnum
{adLockUnspecified = -1,adLockReadOnly = 1,adLockPessimistic = 2,adLockOptimistic = 3,adLockBatchOptimistic = 4
};

(1)adLockReadOnly——缺省值,只读锁定记录。

Recordset对象以只读方式启动,无法更改数据。 只读锁是锁定类型中执行效率最快的,因为它不需要服务器来维持这个记录锁。

(2)adLockPrssimistic——悲观锁定记录。

提供程序通过在编辑之前立即在数据源上锁定记录来确保成功的编辑记录。 当然,这意味着一旦开始编辑,其他用户就无法使用记录,直到您通过调用Update方法来释放锁定。 在不能同时更改数据的系统中使用此类型锁,例如在机票预订系统中。

(3)adLockOptimistic——乐观锁定记录。

这意味着另一个用户可能会在你编辑记录和调用Update方法的期间更改数据,这会造成数据冲突。 在发生冲突的可能性较低或可以轻松解决冲突的情况下使用此锁定类型。

(4)adLockBatchOptimistic——开放式批量更新锁:批量更新模式需要。

许多应用程序一次获取多个行,然后需要进行协调更新,包括要插入,更新或删除的整个行集。 使用批量光标,只需要与服务器通信一次,从而提高了更新性能并降低了网络流量。 使用批量游标库可以创建一个静态游标,然后断开与数据源的连接。 此时,你可以对行进行更改,然后重新连接并将更改发布到批处理中的数据源。

4、游标位置属性

指示光标服务的位置(Recordset对象和Connection对象均可设置)

属性详解:

This property setting affects connections established only after the property has been set. Changing the CursorLocation property has no effect on existing connections.

此属性设置仅影响属性设置后建立的连接。 更改CursorLocation属性对现有连接没有影响。(意即该属性必须在连接建立之前设置)

Cursors returned by the Execute method inherit this setting. Recordset objects will automatically inherit this setting from their associated connections.

由Execute方法返回的游标继承此设置。 Recordset对象将自动从它们的关联连接来继承这个设置。

This property is read/write on a Connection or a closed Recordset, and read-only on an open Recordset.

此属性在一个连接或关闭的记录集上是可读取/写入的,在打开的Recordset上为只读。

CursorLocationEnum
{adUseNone = 1,adUseServer = 2,adUseClient = 3,adUseClientBatch = 3
};

(1)adUseNone——不使用游标服务(这个常量已经过时,并且仅出于向后兼容性的考虑)

(2)adUseServer——服务器游标,默认值。使用数据提供者的或驱动程序提供的游标。这些游标有时非常灵活,对于其他用户对数据源所作的更改具有额外的敏感性。但是,Microsoft Client Cursor Provider(如已断开关联的记录集)的某些功能无法由服务器端游标模拟,通过该设置将无法使用这些功能。

(3)adUseClient——客户端游标。使用由本地游标库提供的客户端游标。 本地游标服务通常允许使用的许多功能可能是驱动程序提供的游标无法使用的,因此使用该设置对于那些将要启用的功能是有好处的。为了向后兼容,还支持同义adUseClientBatch。

5、最常见的问题:获取记录集的RecordCount属性总为-1

分析:

如果将 CursorLocation 属性设置为 adUseClient,则只支持 adOpenStatic 的设置。如果设置了不支持的值,不会导致错误,并将使用最接近支持的 CursorType。

此外当要实现远程数据服务时,在与服务端通信的客户端上使用Recordset 或 Connection对象时, CursorLocation属性只能设置为adUseClient,也就是说CursorType属性的值只能设置为adOpenStatic。

PS:当游标类型CursorType设置为adOpenKeyset时,RecordCount方法也能返回实际的记录数。

解决:

m_pRecordset->CursorLocation = adUseClient;m_pRecordset->Open(_bstr_t(strSQL),m_pConnection.GetInterfacePtr(),adOpenStatic,adLockReadOnly,adOptionUnspecified);adUseClient;m_pRecordset->Open(_bstr_t(strSQL),m_pConnection.GetInterfacePtr(),adOpenStatic,adLockReadOnly,adOptionUnspecified);

6、游标类型或锁定类型的特点

游标类型 优点 缺点
adOpenForwardOnly 低资源要求 不能向后滚动;无数据并发
adOpenStatic 可滚动的     无数据并发
adOpenKeyset

部分数据并发;可滚动的

较高的资源要求;在断开连接的脚本中不可用

adOpenDynamic 高数据并发;可滚动 资源需求最高;在断开连接的脚本中不可用
锁定类型 优点 缺点
adLockReadOnly 低资源要求;可扩展性高 数据不能通过光标更新
adLockBatchOptimistic 批处理更新;支持允许断开连接的方案;其他用户可访问数据 数据可以由多个用户同时改变(可能会造成冲突)
adLockPessimistic 锁定的时候其他用户不能更改数据 锁定的时候会阻止其他用户访问数据
adLockOptimistic 其他用户能够访问数据 数据可以有多个用户同时改变(可能会造成冲突)

7、代码示例

void ADOCnn::AdoCursorsTest(CursorTypeEnum CursorType, LockTypeEnum LockType, CursorLocationEnum CursorLocation)
{AfxOleInit();HRESULT hr;_ConnectionPtr m_pConnection = NULL;m_pConnection.CreateInstance("ADODB.Connection"); //创建Connection对象实例m_pConnection->ConnectionTimeout = 30;  //设置连接超时时间 30sif (m_pConnection == NULL){TRACE("Connection 对象创建失败! 请确认是否初始化了COM环境\r\n");}//连接字符串hr = m_pConnection->Open(_bstr_t(_T("Provider=OraOLEDB.Oracle.1;Password=test;Persist Security Info=True;User ID=test;Data Source=ORCL")),_bstr_t(_T("test")), _bstr_t(_T("test")), adConnectUnspecified);  if (SUCCEEDED(hr))// 测试数据库是否连接成功{TRACE("数据库初始化连接成功!");}_RecordsetPtr m_pRecordset = NULL;m_pRecordset.CreateInstance("ADODB.Recordset");//创建记录集的对象实例m_pRecordset->CursorLocation = CursorLocation;//设置游标位置CString strSQL;strSQL = "select * from test"; m_pRecordset->Open(_bstr_t(strSQL), m_pConnection.GetInterfacePtr(), CursorType, LockType, adOptionUnspecified);
}

需要打开什么样的记录集,只需要调用该函数并设置参数即可。

EG . AdoCursorsTest(adOpenStatic,adLockReadOnly,adUseClient);

参考资料:

https://docs.microsoft.com/en-us/sql/ado/reference/ado-api/ado-api-reference?view=sql-server-2017

ADO 对象的游标类型(CursorTypeEnum)游标位置(CursorLocation)锁定方法(LockTypeEnum)的超详解析以及使用方法相关推荐

  1. mysql 当前记录集不支持书签_存储过程 分页。当前记录集不支持书签。这可能是提供程序或选定的游标类型的限制。...

    ifsession("user")="A0331A2"then'试验存储过程response.Write("存储过程")DIMMyComm, ...

  2. ADO对象之Recordset用法总结:

    在ADO程序中,记录集(Recordset)对象代表一个表的记录集合或者是一个SQL命令或存储过程执行结果.简单地说:记录集实际上缓存了从数据库获得的记录,应用程序可以从记录集中获得每条记录的字段. ...

  3. oracle中游标分类,Oracle 游标分类以及实例

    /*Oracle游标,从字面理解就是游动的光标.用数据库语言来描述就是:游标是映射在结果集中一行数据上的位置实体, 有了游标,用户就可以访问结果集中的任意一行数据了,将游标放置到某行后,即可对该行数据 ...

  4. 游标(概念、优点、分类、静态游标的使用(显示游标(显示游标的属性、遍历显示游标、显示游标的FOR循环)、隐式游标(隐式游标的属性))、动态游标的使用、静态游标和动态游标的区别、更新或删除当前游标数据

    文章目录 游标 游标概念 游标优点 游标分类 静态游标的使用 显示游标 显示游标的属性 遍历显示游标 显示游标的FOR循环 接收显式游标数据的数据类型(普通变量.记录变量.集合变量) 通过游标更新.删 ...

  5. 简述游标原理 mysql_SQL游标原理和使用方法_MySQL

    bitsCN.com 在数据库开发过程中,当你检索的数据只是一条记录时,你所编写的事务语句代码往往使用SELECT INSERT 语句.但是我们常常会遇到这样情况,即从某一结果集中逐一地读取一条记录. ...

  6. mysql 游标原理_SQL 游标原理和使用方法_MySQL

    bitsCN.com 在数据库开发过程中,当你检索的数据只是一条记录时,你所编写的事务语句代码往往使用SELECT INSERT 语句.但是我们常常会遇到这样情况,即从某一结果集中逐一地读取一条记录. ...

  7. JavaScript 中对象的属性类型

    对象的属性类型 JavaScript 中的对象的属性包括数据属性和访问器属性,在 JavaScript 引擎的内部实现中定义了用于描述属性(property)的特性(attribute).规范中将特性 ...

  8. Oracle 11g Release 1 (11.1) 游标——显式游标

    http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/static.htm#CIHCAHJA 本文内容 声明一个游标 打开一个游标 用游标获取一个 ...

  9. 【Oracle】PL/SQL 显式游标、隐式游标、动态游标

    在PL/SQL块中执行SELECT.INSERT.DELETE和UPDATE语句时,Oracle会在内存中为其分配上下文区(Context Area),即缓冲区.游标是指向该区的一个指针,或是命名一个 ...

最新文章

  1. C++ 三五法则,看看你能不能理解
  2. MelGan原理与实践篇
  3. TCP/IP详解--第八章
  4. Java 最坑爹的 10 大功能点!
  5. minio扩展现有的分布式集群:扩大集群规模,增加磁盘数量
  6. VTK:图片之ExtractComponents
  7. memcached协议
  8. 翻版“永恒之蓝”入侵手机 信息安全再临大考
  9. react取消所有请求_react 组件关闭后怎么消除还在进行中的ajax
  10. godaddy mysql 乱码_Godaddy主机乱码的解决方法 | Godaddy美国主机中文指南
  11. ISA2006之二---client
  12. vue 读取ajax数据,详解vue 中使用 AJAX获取数据的方法
  13. 6.Linux中的进程管理
  14. 如何在新系统下重玩老游戏
  15. 谷歌浏览器打不开网页
  16. linux服务器的外网IP查阅方式
  17. 怎么查看无线路由器连接的设备连接服务器,路由器怎么看几个人连接
  18. influxdb删除错误DB contains shards using both inmem and tsi1 indexes.
  19. 江苏计算机学业水平测试多少分过关,江苏学业水平测试的相关问题整理
  20. ERP系统对服装行业的帮助有哪些?

热门文章

  1. 2020树莓派4B安装teamviewer教程
  2. python3 中多继承的顺序问题
  3. 文件夹无法访问、拒绝访问的解决方法
  4. 【C#】 软件打包与制作安装向导(打包成自解压和打包成安装程序)
  5. 除了学习PHP,还应该学什么?
  6. 2022「Cloud 100 China」榜单隆重发布,百望云荣誉登榜
  7. 内蒙古海天公司企业网的规划与设计
  8. C语言----周末舞会
  9. BACKBONE,NECK,HEAD
  10. Map图,散点地图,柱状图,都很精美!