对于sql来说查询的思维方式的面向集合
对于游标来说:思维方式是面向行的

性能上:游标会吃更多内存,减少可见的并发,锁定资源等

当穷尽了while循环,临时表,表变量,自建函数,或其他方式仍然无法实现某些查询的时候,可以考虑使用游标

游标的生命周期由5部分组成:

游标可以很简单,也可以很复杂,取决于游标的参数

游标可以理解为定义在数据集上的指针,可以控制这个指针遍历数据集,或者仅仅指向特定的行,所以游标是定义在以select开始的数据集上的

游标的定义:

DECLARE cursor_name CURSOR [ LOCAL | GLOBAL ]
[ FORWARD_ONLY | SCROLL ]
[ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ]
[ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ]
[ TYPE_WARNING ]
FOR select_statement
[ FOR UPDATE [ OF column_name [ ,...n ] ] ]
[;]

游标分为:游标类型和游标变量,
游标变量遵循T-sql变量的定义方法,支持两种方式赋值,定义时赋值和先定义后赋值
如果定义局部游标:在游标前加 @
如果定义全局的游标,只支持在定义的时候直接赋值,并且不能在游标名称前面加 @
例如:

--定义的全局游标,游标变量没有@,全局游标定义需要直接进行赋值
DECLARE cur_test CURSOR FOR
SELECT * FROM AuthToken AS at --定义的局部游标,需要使用@声明变量
DECLARE @cur_test2 CURSOR
--先声明变量,然后再进行赋值
SET @cur_test2 = CURSOR FOR
SELECT * FROM AuthToken AS at

游标的参数:
Local和global二选一

Local:意味着游标的生存周期只在批处理或者函数或者存储过程中可见,
Global:意味着游标对于特定连接作为上下文,全局内有效

全局游标:在批处理后依然有效,
局部游标:在批处理结束后被隐式释放,无法在其他批处理中调用

--定义的全局游标,游标变量没有@,全局游标定义需要直接进行赋值
DECLARE cur_test CURSOR GLOBAL FOR
SELECT * FROM AuthToken AS at DECLARE cur_test CURSOR LOCAL FOR
SELECT * FROM AuthToken AS at

如果不指定,默认为global

FORWARD_ONLY 和SCROLL二选一

forward_only:意味着游标只能从数据集开始向数据集结束的方向读取,Fetch next是唯一选项,
scroll支持游标在定义的数据集中向任何方向,或者任何位置移动

例如:

--不加参数,默认为 forward_only
DECLARE Test_Cursor CURSOR FOR
SELECT * FROM AuthToken AS at -- 加scroll参数,支持游标指针向数据集的任意方向移动,
DECLARE Test2_Cursor CURSOR SCROLL FOR
SELECT * FROM AuthToken AS at -- 加FORWARD_ONLY参数,支持游标指针 只能从 数据集开始方向向结束方向移动,
DECLARE Test3_Cursor CURSOR FORWARD_ONLY FOR
SELECT * FROM AuthToken AS at OPEN Test_Cursor
OPEN Test2_Cursor
OPEN Test3_Cursor --只支持从数据集开始方向向结束方向移动
FETCH NEXT FROM Test_Cursor
FETCH NEXT FROM Test3_Cursor
--SCROLL 支持向任意方向移动
FETCH NEXT FROM Test2_Cursor
FETCH LAST FROM Test2_Cursor

static,keyset, dynamic 和 fast_forward 四选一

这四个参数是游标所在数据集所反应的表内数据和游标读取出的数据的关系

static:意味着当游标被建立时,将会创建 for后面的 select语句所包含数据集的副本存入 tempdb数据库中,任何对于底层表内数据的更改都不会影响到游标的内容

dynamic:和static相反,当底层数据库表内内容更改时,游标的内容也随之改变,下一次 fetch中,数据内容会随之改变

keyset:是上面两种的折中方案:将游标所在结果集的唯一能确定每一行的主键存入tempdb,当结果集中任何行改变或者删除时,@@Fetch_status 会为 -2,keyset无法探测新加入的数据

fast_forward:是forward_only的优化版本,forward_only执行的是 静态计划,
而Fast_forward是根据情况进行选择采用动态计划还是静态计划,

Read_only ,Scroll_locks,Optimistic三选一
Read_only:意味着声明的游标只能读取数据,游标不能做任何更新操作
scroll_locks:将读入游标的所有数据进行锁定,防止其他程序进行更改,以确保更新的绝对成功

Optimistic:不锁定任何数据,当需要在游标中更新数据时,如果底层表数据更新,则游标内数据更新不成功,如果底层表数据未更新,则游标内表数据可以更新

打开游标:

当游标定义完,需要打开后才能使用
Open test_cursor

注意:当全局游标和局部游标变量重名时,默认会打开局部变量游标

3 使用游标:

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

支持6种移动选项
到第一行:first
最后一行:last
下一行:next
上一行:prior
直接跳到某行:absolute(n)
相对于目前跳几行(relative(n))

对于未指定scroll选项的游标来说,只支持next取值

例如:

DEALLOCATE test_cursor
--定义一个全局游标,并且支持向任意方向移动
DECLARE test_cursor CURSOR SCROLL FOR
SELECT c.Nickname FROM dbo.Customer AS c
--定义好之后需要首先打开游标
OPEN test_cursor DECLARE @a NVARCHAR() --使用游标:取第一行数据到@a
FETCH FIRST FROM test_cursor INTO @a
PRINT @a --取当前位置的第n行数据(取绝对位置)
FETCH ABSOLUTE FROM test_cursor INTO @a
PRINT @a --取相对位置
FETCH RELATIVE FROM test_cursor INTO @a
PRINT @a --取当前位置的下一行数据
FETCH NEXT FROM test_cursor INTO @a
PRINT @a
--取最后一条数据
FETCH LAST FROM test_cursor INTO @a
PRINT @a
--取游标的当前位置的上一行数据
FETCH PRIOR FROM test_cursor INTO @a
PRINT @a --游标使用完之后需要关闭游标
CLOSE test_cursor --如果不再需要游标,可以进行删除
DEALLOCATE test_cursor

游标经常会和全局变量 @@Fetch_status 与while循环来共同使用,以便达到遍历游标所在数据集的目的

例如:

DECLARE Test_Cursor CURSOR SCROLL FOR
SELECT c.Id,c.Nickname FROM Customer AS c OPEN Test_Cursor
DECLARE @i INT
DECLARE @name NVARCHAR() WHILE @@FETCH_status =
BEGIN
PRINT @i
PRINT @name
FETCH NEXT FROM Test_Cursor INTO @i,@name
END
CLOSE Test_Cursor
DEALLOCATE Test_Cursor

使用游标注意点:

1 游标能不用就尽量不要用游标
2 用完之后一定要关闭和释放
3 尽量不要在大量数据上定义游标
4尽量不要使用游标上更新数据
5 尽量不要使用insensitive,static,keyset这些参数定义游标
6 如果可以,尽量使用fast_forward关键字定义游标
7如果只对数据进行读取,当读取只用到Fetch next选项,则最好使用 forward_only参数

Sqlserver 关于游标的更多相关文章

  1. SqlServer之游标深入

    原创文章,转载必需注明出处:http://www.ncloud.hk/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/introduce-for-sqlserver-curs ...

  2. SqlServer 利用游标批量更新数据

    SqlServer 利用游标批量更新数据 Intro 游标在有时候会很有用,在更新一部分不多的数据时,可以很方便的更新数据,不需要再写一个小工具来做了,直接写 SQL 就可以了 Sample 下面来看 ...

  3. 【SqlServer】SqlServer的游标使用

    什么是游标 结果集,结果集就是select查询之后返回的所有行数据的集合. 游标则是处理结果集的一种机制吧,它可以定位到结果集中的某一行,多数据进行读写,也可以移动游标定位到你所需要的行中进行操作数据 ...

  4. SQLServer中游标是如何处理数据的?

    游标(Cursor)是处理数据的一种方法,为了查看或者处理结果集中的数据,游标提供了在结果集中一次以行或者多行前进或向后浏览数据的能力.我们可以把游标当作一个指针,它可以指定结果中的任何位置,然后允许 ...

  5. sqlserver 使用游标过程中出现的错误

    下面的见解是在使用游标的过程中做的日记.我也是第一次使用,如果有什么不对的地方请批评指正,大家一起努力. 1. 消息 16951,级别 16,状态 1,过程 usp_proc,第 16 行      ...

  6. SQLServer中游标实例介绍(转)

    引言 我们先不讲游标的什么概念,步骤及语法,先来看一个例子: 表一 OriginSalary                      表二 AddSalary 现在有2张表,一张是OriginSal ...

  7. SQLserver 存储过程游标使用

    ALTER PROCEDURE [dbo].[p_DeleteStretchData] ) , ) AS BEGIN ) ) declare @stretch_cursor cursor -- 声明游 ...

  8. 使用sqlserver的游标功能来导数据的常见写法

    一定要自己试过才知道么? 你也没试过吃屎,你怎么知道屎不能吃,难道你试过啊...(没有愤怒的意思) ),),) declare cursor_data CURSOR FOR SELECT [UserN ...

  9. sqlserver 存储过程 游标实例

    if exists(select * from sysobjects where id = object_id(N'dbo.test_cursor') and type = 'P') drop PRO ...

随机推荐

  1. SQLServer2008设置开启INTERNET远程连接

    SQL Server 2008默认是不允许远程连接的,sa帐户默认禁用的,如果想要在本地用SSMS连接远程服务器上的SQL Server 2008,需要做两个部分的配置: 使用sa账户登录SQL Se ...

  2. Nginx启动停止命令

    操作环境是Windows 一.nginx命令:启动nginx 在Windows上安装好nginx后,我们需要启动nginx服务,启动nginx服务的命令行操作主要有两种方式,即 cd D:\opens ...

  3. java获取照片相关属性

    package test; import java.io.File; import java.util.Iterator; import com.drew.imaging.jpeg.JpegMetad ...

  4. 机器学习笔记之遗传算法(GA)

    遗传算法是一种大致基于模拟进化的学习方法,假设常被描述为二进制串.在遗传算法中,每一步都根据给定的适应度评估准则去评估当前的假设,然后用概率的方法选择适应度最高的假设作为产生下一代的种子.产生下一代的 ...

  5. cocos2d-x CCListView

    转自:http://blog.csdn.net/onerain88/article/details/7641126 cocos2d-x 2.0 版更新了,把opengl 1.1 替换为opengl 2 ...

  6. 配置DNS服务器IP

    #############################脚本功能及说明#################### #该脚本用来在本地服务器上配置DNS服务器IP #创建时间:2014-10-22 ## ...

  7. 通过注册表查看已安装 .NetFramework 版本

    gci "hklm:\SOFTWARE\Microsoft\NET Framework Setup\NDP" | % {(Get-ItemProperty registry::$_ ...

  8. python的一些总结4

    这篇继续水 但是在水的的基础上 让搭建能正常使用flask 搭建一个站 上篇讲到在 模板view中 输入{{xx }} 可以打印 后台传的值. 这篇讲一下 循环控制 条件控制等 修改后台代码: @ap ...

  9. sed命令查找<media/msm_cam_sensor.h>替换为"len_msm_cam_sensor.h"

    sed -i 's:<media/msm_cam_sensor.h>:"len_msm_cam_sensor.h":g' $(find . -name "*. ...

  10. 使用命令xrandr设置当前系统的显示分辨率及显示的旋转脚本

    /*********************************************************************  * Author  : Samson  * Date   ...