它基于我面临的面试问题.
非常简短的定义可以
它可用于操纵查询返回的行.
除了使用光标(分列在这里的MSDN),我在我的脑海的一个问题是,如果我们可以利用执行查询或存储过程中的所有操作(如果我没有错,就像我们可以使用Transact-SQL对于ms-sql),我们应该使用游标吗?
与大结果集相比,使用游标就像使用视频流而不是一次性下载视频,并在下载时观看它.如果你下载,你必须有一些空间和耐心等待下载完成.现在,无论您的机器或网络速度有多快,每个人都以相同的速度观看电影.
通常,任何查询都会在一次活动中发送到服务器,执行,并通过网络将结果集发送给您.游标将允许您逐行访问数据,并仅在您请求时对每行进行流式处理(实际上可以查看它).
光标可以节省您的时间 - 因为您无需等待处理和下载完整的记录集
它将节省您在服务器和客户端上的内存,因为它们不必将大量内存专用于结果集
负载均衡网络和服务器 - 在"突发"模式下工作通常更有效,但它可以完全阻止您的服务器和网络.多用户环境很少需要这种延迟.流媒体为其他操作留出了空间.
允许对查询表(在某些条件下)上的操作直接影响游标.因此,当您将光标放在行上时,其他进程可以读取,更新甚至删除其他行.这有助于特别是非常繁忙的表,许多并发读写.
然而,这给我们带来了一些警告:
一致性:使用游标,您(通常)不会在数据的一致快照上操作,而是在一行上操作.因此,您的并发/一致性/隔离保证从整个数据库(ACID)只丢失到一行.您通常可以告知您的DBMS您想要的并发级别,但如果您太过挑剔(锁定您所在的完整表),您将丢弃服务器端的许多资源节省.
单独传输每一行可能效率非常低,因为每个数据包都有协商开销,您可以通过每个数据包发送大的,可能是压缩的数据块来避免这种情况.(没有DB服务器或客户端库是愚蠢到足以单独传输每一行,两端都有缓存和分块,但仍然是相关的.)
游标更难做对.考虑使用大结果集的查询,激励您使用带有聚合函数的GROUP BY子句的游标.(此类查询在数据仓库中很常见).GROUP BY可以完全废弃您的服务器,因为它必须立即生成并存储整个结果集,甚至可能在其他表上持有锁.
经验法则:
如果您处理小型,快速创建的结果集,请不要使用游标.
游标在临时性,复杂性(引用性),具有大结果集和低一致性要求的顺序性查询方面表现优异.
"顺序性"表示查询中的GROUP BY子句中没有聚合函数.服务器可以懒惰地决定为光标计算10行以从缓存中消耗并同时执行其他操作.
HTH
游标是一种允许您迭代集合中记录的工具.它有订单和当前记录的概念.
通常,SQL
使用多集合进行操作:这些是一组可能重复的记录,没有给定的顺序,作为一个整体.
说,这个查询:
SELECT * FROM a JOIN b ON b.a = a.id
,在multisets a
和b
.
此查询中的任何内容都不会对记录的顺序,存储方式,访问顺序等进行任何假设.
这允许抽象出实现细节,并让系统尝试选择最佳算法来运行此查询.
但是,在转换完所有数据后,最终需要以有序的方式逐个访问记录.
您不关心电话簿的条目是如何存储在硬盘驱动器上的,但打印机确实要求它们按字母顺序输入; 并且格式化标签应单独应用于每个记录.
这正是游标发挥作用的地方.每次在客户端处理结果集时,都使用游标.您没有从服务器获取兆字节的未排序数据:您只需获得一个小变量:结果集描述符,只需编写如下内容:
while (!rs.EOF) { process(rs); rs.moveNext(); }
这是为您实现所有这一切的光标.
这当然涉及数据库 - 客户端交互.
至于数据库本身:在数据库中,你很少需要游标,因为正如我上面所说的,几乎所有的数据转换都可以使用set操作更有效地实现.
但是,也有例外:
分析操作中SQL Server
都很差实施.例如,累积和可以使用游标比使用基于集合的操作更有效地计算
处理数据块.存在这样的情况:应该将基于集合的操作顺序地应用于集合的一部分,并且应该独立地提交每个块的结果.虽然仍然可以使用基于集合的操作来执行此操作,但是通常使用游标是更优选的方法.
在本机不支持它的系统中的递归.
您也可能会发现这篇文章值得一读:
Misfit游标岛