草庐IT

SQL Server 游标

纪智坚 2024-02-08 原文
游标
游标是邪恶的!在关系数据库中, 查询是面向集合的,而游标打破了这个规则, 游标是面向记录的(行),正确的面向集合的思维方式是这样的

 

而对于游标来说

 

 

这也就是为什么游标是邪恶的,同样的, 在性能上,游标会吃更多的内存,减少可用的并发,占用宽带,锁定资源,更多的代码量
从游标读取数据的方式不难看出为什么占用更多的资源,比如:当你从ATM里一次取1000效率高呢?还是10次取100快?

 

既然游标是邪恶的,为什么我们还要学习游标呢?
存在即合理,就像前面说的,IN与NOT IN是无视索引的,会引发查询一系列的隐藏问题,但是就是有它自己的用处。当我们穷尽了WHILE和子查询或者其他条件仍然无法完成查询的效果,就可以使用游标来实现

 

T-SQL中游标的生命周期以及实现
游标由5个部分组成
1.定义一个游标
在T-SQL,定义一个游标可以是很简单的,也可以是复杂的,取决于游标的参数,而游标的参数设置决定了你对游标原理的理解程度
游标其实可以理解为一个定义在特定 数据集上的指针(如果对数据集的概念不理解可以看上一篇文章),我们可以控制这个指针遍历数据集,或者指向特定行,所以游标是在以SELECT开始的数据集上的
DECLARE cursor_name CURSOR [ LOCAL | GLOBAL](作用域)
        [FORWARD_ONLY | SCROLL](方向)
        [STATIC | KEYSET | DYNAMIC | FAST_FORWARD](类型)
        [READ_ONLY | SCROLL_LOCK | OPTIMISTIC]
        [TYPE_WARNING]
        FOR SELECT col1,col2 FROM table_name

下面就仔细讲一下这句语句的意义

游标分为全局游标和局部游标,对于局部游标来说,遵循T-SQL变量的定义方法(变量的定义可以参考前面文章),局部游标变量支持两种方式赋值,定义时候赋值,或者先定义后赋值,定义时要在游标名前面加‘@’,如果定义全局游标,就不用加‘@’,只支持定义时直接赋值

下面讲参数的选择:

LOCAL和GLOBAL二选一

LOCAL意味着游标的s生存周期只在批处理,函数或者存储过程中可见,类似局部变量,而GLOBAL在在整个会话窗口中可见,全局有效

如果不指定作用域,默认为GLOBAL

FORWARD_ONLY和SCROLL二选一

FORWARD_ONLY意味着游标只能从数据集开始的地方向数据集结束的地方的方向读取,FETCH NEXT 为唯一选项。而SCROLL支持游标在定义的数据集中向任何方向或者任何位置移动。不加参数则默认为FORWARD_ONLY

 

STATIC,KEYSET,DYNAMIC和FAST_FORWARD四选一

这四个关键字表示游标所在数据集所反映的表内数据与游标读取的数据关系

STATIC:当游标被创建时,将会创建FOR后面的SELECT语句所包含数据集的副本存到tempdb数据库中,任何底层表内的数据的更改都不会影响到游标的内容

DYNAMIC:是和STATIC相反的极端,当底层数据库被更改时,游标的内容也会跟着得到反应,在下一次FETCH中,数据内容也会跟着改变

KEYSET:可以理解为介于STATIC与DYNAMIC的折中方案,将游标所在结果集的唯一确定每一行主键存入tempdb,当结果集中任何行改变或删除时,@@FETCH_STATUS会为-2,KEYSET无法探测新加入的数据

FAST_FORWARD:可以理解为FORWARD_ONLY的优化版,FORWARD_ONLY执行的是静态计划,而FAST_FORWARD是根据情况来选择动态计划还是静态计划,大多数情况下FAST_FORWARD的性能要比FORWARD_ONLY略好

READ_ONLY,SCROLL_LOCKS和OPTIMISTIC三选一

READ_ONLY:意味着声明的游标只能读取数据,游标不能做任何操作

SCROLL_LOCKS:是另一种极端,将读入游标的所有数据进行锁定,防止其他程序进行修改,以确保更新的绝对成功

OPTIMISTIC:相对来说比较好一点的选择,OPTIMISTIC不锁定任何数据,当需要在游标中更新数据时,如果底层表数据更新,则游标内数据更新不成功,如果底层数据未更新,则游标表内数据可以更新。

2.打开游标

定义完游标后,使用OPEN cursor_name即可以打开游标

3.读取游标数据

游标的使用分为两部分,一部分是操作游标在数据集内的指向,另一部分是将游标所指向的部分行或者全部行进行操作

6种移动方式:第一行(FIRST),最后一行(LAST),下一行(NEXT),上一行(PRIOR),直接跳向某行(ABSOLUTE n),相对于目前行的第几行(RELATIVE n)

游标经常会与全局变量@@FETCH_STATUS与WHILE循环配合使用,以达到遍历游标所在的数据集的目的

4.关闭游标
使用完游标后要关闭游标:CLOSE cursor_name
5.释放游标
当游标不再使用了一定要释放游标:DEALLOCATE cursor_name
全局变量@@FETCH_STATUS
每执行一个FETCH后,都会返回一次@@FETCH_STATUS状态值,判断FETCH是否执行成功
0:表示成功执行FETCH
-1:表示FETCH语句失败,例如移动指针使其超出的结果集
-2:表示被提取的行不存在
建议
  • 如果能不用游标就别用,游标永远是无奈下的选择,是一种非常邪恶的存在,面向记录的特性会比面向集合的特性慢上很多倍
  • 用完一定要关闭与释放
  • 有大量数据的时候不要用游标
  • 尽量不要用游标更新数据
  • 尽量不要使用INSENSITIVE,STATIC和KEYSET这些参数定义游标,因为占用了其他空间 
  • 如果可以,尽量使用FAST_FORWARD关键字定义游标
  • 如果只对数据进行读取,当读取只用到FETCH NEXTx选项,最好使用FORWARD_ONLY参数

 

 

 

有关SQL Server 游标的更多相关文章

  1. ruby - 是否有任何使用游标或智能提取的 Ruby ORM? - 2

    我正在寻找一个RubyORM来替代ActiveRecord。我一直在研究Sequel和DataMapper。它们看起来很不错,但是它们似乎都没有做基本的事情:在不需要时不将所有内容加载到内存中。我的意思是我已经在ActiveRecord和Sequel上尝试了以下(或等效的)在有很多行的表上:posts.each{|p|putsp}他们俩都为内存疯狂。他们似乎将所有内容都加载到内存中,而不是在需要时获取内容。我在ActiveRecord中使用了find_in_batches,但这不是一个可接受的解决方案:ActiveRecord不是一个可以接受的解决方案,因为我们在使用它时遇到了太多问题

  2. javascript - jquery 设置 tabindex 和游标 - 2

    我有以下代码将tabindex分配给我的表单ID“register1”。一旦分配了tabindexes,我想将光标放在表单上的第一个输入或选择列表项上(tabindex=1的项目)。但以下行:$('#register1').find('input').attr('tabindex',1).select();重置所有输入的tabindex。完整代码:$(function(){vartabindex=1;$('#register1').find('input,select').each(function(){if(this.type!="hidden"){var$input=$(this)

  3. javascript - Node.js Twitter API 游标 - 2

    我正在使用npm-twit获取特定帐户的关注者。TwitterAPI从单个GET请求返回最多5000个结果。如果我正在查询的用户拥有超过5000个关注者,则数据会返回“next_cursor”值。要获得接下来的5000个结果,我需要重新运行GET函数,将“next_cursor”值作为参数传递给它。我似乎不知道该怎么做。我在考虑while循环,但我无法重置全局变量,我想是因为作用域:varcursor=-1while(cursor!=0){T.get('followers/ids',{screen_name:'twitter'},function(err,data,response){

  4. javascript - 用于使用游标对 api 进行分页的 Axios 递归 - 2

    如何使用axios对带有游标的API进行分页?我想递归调用此函数直到response.data.length并在完成后返回包含集合中所有项目的整个数组。另外,值得注意的是,我必须将光标传递到后续调用中。functiongetUsers(){returnaxios.get('/users')//APIsupportsacursorparam(?after=).then(response=>{//returnsanarraywithacursor//seeresponsebelowconsole.log(response.data)})}示例响应:{"total":100,"data":[

  5. javascript - 是否可以在 nodejs 中倒带文件描述符游标? - 2

    这就是我在完美世界中会做的事情:fs.open('somepath','r+',function(err,fd){fs.write(fd,'somedata',function(err,written,string){fs.rewind(fd,0)//thisdoesn'texist})})这是我当前的实现:returnasync.waterfall([function(next){//openingafiledescriptortowritesomedatareturnfs.open('somepath','w+',next)},function(fd,next){//writing

  6. javascript - react : Resizing a div including handlers, 不同的游标,即 ns-resize - 没有 jquery - 2

    我正在寻找一种允许用户使用句柄和所有相关光标调整div大小的简单方法。我看到很多使用jquery的示例,但我想在React中使用它,不需要jquery。有谁知道这样做的简单方法吗?我假设纯js,css。我真的不想为此使用react组件,因为我需要在标准div上启用调整大小。当然,它是与reactjs一起使用的,有没有更现代的方法可以在没有jquery的情况下做到这一点?**编辑**这些是可用于每个可调整大小的点的光标e-resizene-resizen-resizenw-resizes-resizese-resizew-resizesw-resize 最佳答

  7. javascript - 调试 meteor 客户端时,如何查看集合或游标内容? - 2

    我正在尝试调试meteorapp的客户端.如何查看集合的内容?更具体地说,我如何像查看控制台中的普通对象一样查看LocalCollection.Cursor的内容?在服务器端,db.collectionName.find()将输出JSON,db.collectionName.find().pretty()使集合的内容易于访问阅读和检查。我如何在客户端使用“minimongo”集合做类似的事情? 最佳答案 您可以执行Collection.find({}).fetch()来查看集合中的对象数组。然后,您可以展开每个对象以查看其属性。

  8. javascript - 我们可以将游标设置为 session 变量吗? - 2

    我试图将游标设置为session变量,但它似乎不起作用。有人知道吗??我的代码:Meteor.call('apiresult',function(e,result){console.log(result);Session.set("object",result)});//gettingvariablevarabc=Session.get("object");returnabc.skimlinksProductAPI.numFound;好像没用 最佳答案 游标可以实际上存储在Session中...有时。打开leaderboardapp

  9. javascript - 如何结合 Firestore orderBy desc 和 startAfter 游标 - 2

    我正在尝试查询firestore中的列表,该列表应按降序日期属性排序,并使用startAfter游标对结果进行分页。正如您在下面的代码片段中所看到的,一旦我将orderBy('date','desc')与startAfter(lastDoc.date)结合使用,这就会失败。我想知道我做错了什么。有什么想法吗?//thisactuallyworks//butitissortedbyascendingdatesdb.collection('tanks').doc(tankId).collection('documentations').orderBy('date').startAfter(

  10. javascript - 多个属性上的索引数据库游标范围 - 2

    我在indexeddb对象存储上有两个属性的复合索引,并希望根据这两个属性的范围检索游标。这是商店中的示例对象:{species:'Oak',xcoord:123456,ycoord:654321}和索引:treeStore.createIndex("treelocation",["xcoord","ycoord"],{unique:false});索引创建成功,我可以在Chrome开发者工具中看到它,但是现在我想打开一个在x和y坐标上都有键范围的光标(这将是map的范围).在线搜索我看不到如何执行此操作,并且使用键范围数组打开索引似乎不起作用。 最佳答案

随机推荐