SQL Server游标

游标的定义是啥子?

标准定义:

游标是SQL 的一种数据访问机制。可以将游标简单的看成是查询的结果集的一个指针,可以根据需要在结果集上面来回滚动,浏览需要的数据。

我的定义:

使用游标(cursor)的一个主要的原因就是把集合操作转换成单个记录处理方式。
把表比作一栋房子,把表中的数据比作居住在房子里的人。每个房子不可能只有客厅,必须有厕所,卧室等。

把游标比作厕所,第一个人(小王)进去了,后面的人就不能进了(当然,你要是能挤一挤我是无话可说的),此时“厕所”的状态就是小王正在上厕所,只有等小王上完厕所(处理完数据)之后下个人才可以继续上,可以插队(使用限制语句),按照用户自己的意愿来插队(显示和处理这些记录),这就是游标(厕所)的定义:用来把集合操作变成单个处理方式。

缺点就是慢!上厕所的时间不可能固定,说不定玩会手机,刷个抖音,别人就炸了。

优点也是有的,举一个例子:
小王上厕所出来了,第二个人(老二)是想上小便,而第三个人(小三)是想开大,此时他们俩通过沟通,老二让小三先去,这样是可以的。这就是允许程序对由查询语句select返回的行集合中的每一行执行相同或不同的操作,而不是对整个行集合执行同一个操作

实例

这是books表结构👇
在这里插入图片描述
这是books表数据,先把level这条字段看为空(看不见看不见你👀)👇
在这里插入图片描述

1.定义游标

--declare 游标名 cursor for sql语句
declare cur_books cursor 
for 
select id,price from books

2.打开游标

--这不用多说了吧?
open cur_books

3.获取数据

--获取数据ID,PRICE
DECLARE @ID INT--定义一个变量用来接收id
DECLARE @PRICE DECIMAL(18,0)--定义一个变量用来接收price
FETCH NEXT FROM cur_books INTO @ID,@PRICE

4.循环获取

--循环获取数据
--如果price小于50为便宜
--大于等于50且小于100为中等
--大于等于100为贵
--并更改他的level字段
WHILE(@@FETCH_STATUS=0)
BEGIN
 IF(@PRICE<50)
 UPDATE BOOKS SET Level='便宜' WHERE ID=@ID
 ELSE IF(@PRICE<100)
 UPDATE BOOKS SET Level='中等' WHERE ID=@ID
 ELSE
 UPDATE BOOKS SET Level='贵' WHERE ID=@ID
 FETCH NEXT FROM cur_books INTO @ID,@PRICE
END

5.关闭并释放游标

--关闭游标
CLOSE cur_books
--释放游标
DEALLOCATE cur_books

--不释放游标的话,在某些场合下会导致代码出错,想详细了解建议百度

好了,游标就讲到这,我去WC了!再见!!

<think>我们参考了引用内容,其中[^1]强调了在SQL中应优先考虑基于集合的操作而非游标,因为游标是逐行处理,效率较低;[^2]则给出了一个静态游标的使用示例。用户明确询问SQLServer游标的使用教程或常见问题解决方案,因此我们将从以下几个方面构建回答:1.游标的基本概念与类型:解释游标是什么,静态游标、动态游标等类型区别2.游标的使用步骤:声明、打开、获取数据、循环处理、关闭释放3.游标的适用场景和替代方案:说明何时应避免使用游标,以及替代方案(如基于集合的操作)4.常见问题解决方案:例如游标性能优化、避免死锁等根据引用[^2]的示例代码,我们给出一个更详细的游标使用示例,并加入中文注释。同时,根据用户需求,生成相关问题。</think> ### SQL Server 游标使用指南 #### 一、游标基本概念 游标(Cursor)是SQL Server中用于**逐行处理查询结果**的数据库对象。与基于集合的操作不同,游标允许逐行访问数据,适用于需要精细控制的场景[^1]。但需注意: - **优先使用集合操作**:SQL设计核心是基于集合的操作,游标会降低性能(尤其大数据量时) - **适用场景有限**:仅当无法用单条SQL实现时才考虑游标 #### 二、游标类型对比 | 类型 | 特点 | |--------------|----------------------------------------------------------------------| | **静态游标** | 创建时复制数据快照,不反映后续数据修改(`STATIC`) | | **动态游标** | 实时反映数据变化(默认类型,需显式声明`DYNAMIC`) | | **键集驱动** | 仅跟踪主键变化(`KEYSET`) | > 参考:[^2]中博主"二月十六"的《SQL SERVER 游标使用》详细区别 #### 三、游标使用教程 1. **声明游标** ```sql DECLARE my_cursor CURSOR STATIC -- STATIC静态/DYNAMIC动态 FOR SELECT name, id FROM users WHERE status=1 -- 查询逻辑 ``` 2. **打开与操作游标** ```sql -- 声明变量 DECLARE @name VARCHAR(50), @id INT OPEN my_cursor -- 打开游标 -- 循环读取数据 FETCH NEXT FROM my_cursor INTO @name, @id WHILE @@FETCH_STATUS = 0 -- 成功获取数据 BEGIN -- 业务逻辑(示例:打印+更新) PRINT '处理用户: ' + @name UPDATE orders SET processed=1 WHERE user_id=@id FETCH NEXT FROM my_cursor INTO @name, @id -- 获取下一行 END ``` 3. **关闭与释放资源** ```sql CLOSE my_cursor -- 关闭游标 DEALLOCATE my_cursor -- 释放内存资源 ``` #### 四、常见问题解决方案 1. **性能优化** - 使用`FAST_FORWARD`只进游标(轻量级) - 限制处理行数(添加`TOP`子句) - 替代方案:尝试用`WHILE`循环或CTE递归 2. **@@FETCH_STATUS异常处理** ```sql IF @@FETCH_STATUS = -1 -- 无数据 PRINT '游标数据已读完' IF @@FETCH_STATUS = -2 -- 行被删除 PRINT '当前行已被删除,跳过处理' ``` 3. **死锁避免** - 操作前加`WITH (NOLOCK)`提示(脏读风险) - 缩短事务时间:在循环内提交小事务 4. **动态SQL整合** ```sql DECLARE @sql NVARCHAR(MAX) = 'SELECT * FROM products' DECLARE my_cursor CURSOR FOR EXEC sp_executesql @sql -- 动态SQL支持 ``` #### 五、使用建议 1. **避免场景**:批量更新/聚合计算(改用`UPDATE FROM`或窗口函数) 2. **必须使用场景**: - 逐行调用存储过程 - 级联操作(如根据A表结果动态修改B表) 3. **资源管理**:务必在结束时关闭游标,防止内存泄漏 > 关键原则:**能用集合操作解决的问题,绝对不用游标**[^1]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值