MSSQL里头怎么用游标管理数据,创建游标那些事儿讲讲吧
- 问答
- 2026-01-23 21:40:24
- 3
在MSSQL里,处理数据最常见的方式是使用SELECT语句一下子把一堆数据抓出来,或者用UPDATE一句更新所有符合条件的数据,这种方式很快,也很省资源,有时候你会遇到一些特殊情况,需要像看清单一样,一行一行地检查或处理数据,这时候就需要用到“游标”这个东西了。
你可以把游标想象成一个可以移动的指针,或者是你读书时用的手指头,你用手指头一行一行地指着书上的字来读,游标也是类似,它能在SQL查询结果集里一行一行地移动,让你有机会对每一行数据进行单独的操作。
为什么要用游标?
虽然一句SQL处理所有数据很高效,但并非万能,你需要根据每一行数据的具体值,去调用一个复杂的存储过程;或者你需要逐行计算累积值,而每一行的计算都依赖于前一行的结果;又或者你需要逐行检查数据,并根据不同的条件执行完全不同的操作,在这些“逐行处理”的场景下,游标就派上用场了。
创建和使用游标的基本步骤
使用游标不像写一句SELECT那么简单,它有一套固定的“仪式感”,需要按步骤来,根据微软官方文档(MSDN)中关于DECLARE CURSOR的说明,主要分为这么几步:
-
声明游标:就是告诉SQL Server,你要创建一个什么样的游标,它的“数据来源”是哪条查询语句。
DECLARE cursor_name CURSOR FOR SELECT column1, column2 FROM your_table WHERE some_condition;
这里,你定义了一个名为
cursor_name的游标,它里面装着从your_table表里查询出来的column1和column2数据。 -
打开游标:声明好之后,游标还是关闭状态,你需要用
OPEN命令打开它,这时SQL Server才会真正去执行你定义的那条SELECT语句,并把结果集准备好。
OPEN cursor_name;
-
获取数据:这是游标的核心操作,用
FETCH命令从游标里把当前指向的那一行数据取出来,放到变量里供你使用,游标会自动移动到下一行。FETCH NEXT FROM cursor_name INTO @variable1, @variable2;
你需要提前定义好
@variable1和@variable2这些变量,它们的类型要和SELECT语句里的列类型匹配,第一次执行FETCH NEXT会取回第一行数据。 -
循环处理:你不可能手动写很多遍
FETCH,所以通常会把FETCH放在一个WHILE循环里,你需要检查每次FETCH是否成功取到了数据,SQL Server提供了一个全局变量@@FETCH_STATUS,当它等于0时,表示成功取到了一行数据。WHILE @@FETCH_STATUS = 0 BEGIN -- 在这里对 @variable1, @variable2 进行处理,比如打印、计算、更新其他表等。 PRINT '处理数据:' + CAST(@variable1 AS VARCHAR) + ', ' + CAST(@variable2 AS VARCHAR) -- 获取下一行 FETCH NEXT FROM cursor_name INTO @variable1, @variable2; END这个循环会一直执行,直到
FETCH不到更多数据(即@@FETCH_STATUS不再为0)为止。 -
关闭游标:当数据处理完毕后,你应该关闭游标,释放它占用的部分资源。

CLOSE cursor_name;
-
释放游标:最后一步,彻底删除游标的定义,释放所有相关资源,这是一个好习惯。
DEALLOCATE cursor_name;
一个简单的例子
假设我们有一个Employees表(员工表),里面有EmployeeID和Salary(工资)字段,我们想给每个员工涨工资,但涨的幅度不一样:工资低于5000的涨500,高于等于5000的涨200,这种一行一行的判断和更新,用游标就挺合适。
-- 1. 声明变量
DECLARE @EmpID INT, @CurrentSalary DECIMAL(10,2);
-- 2. 声明游标
DECLARE salary_cursor CURSOR FOR
SELECT EmployeeID, Salary FROM Employees;
-- 3. 打开游标
OPEN salary_cursor;
-- 4. 获取第一行数据
FETCH NEXT FROM salary_cursor INTO @EmpID, @CurrentSalary;
-- 5. 循环处理
WHILE @@FETCH_STATUS = 0
BEGIN
-- 根据当前行的工资值决定更新逻辑
IF @CurrentSalary < 5000
UPDATE Employees SET Salary = Salary + 500 WHERE EmployeeID = @EmpID;
ELSE
UPDATE Employees SET Salary = Salary + 200 WHERE EmployeeID = @EmpID;
-- 获取下一行
FETCH NEXT FROM salary_cursor INTO @EmpID, @CurrentSalary;
END
-- 6. 关闭游标
CLOSE salary_cursor;
-- 7. 释放游标
DEALLOCATE salary_cursor;
重要提醒:游标的“坏处
虽然游标在某些场景下是唯一的选择,但你必须清楚它的缺点,正如SQL Server性能优化相关文档中常提到的,游标存在以下问题:
- 性能低下:它是一行一行处理的,相当于在数据库内部搞了个小循环,如果数据量很大(比如几十万行),它会非常慢,因为每处理一行都可能产生一次磁盘I/O和锁操作。
- 占用资源多:游标会在整个处理过程中一直保持一些锁和临时资源,可能会阻塞其他用户的操作。
- 代码冗长:比起一句
UPDATE...CASE...WHEN...这样的集合操作,游标的代码要长得多,也更难维护。
总结一下
游标是MSSQL中用于逐行处理数据的强大工具,适用于复杂的、无法用单一SQL语句完成的业务逻辑,它的使用有固定的套路:声明、打开、循环获取并处理、关闭、释放,因为它效率不高,所以应该被视为“最后的手段”,在能用普通的UPDATE、INSERT、DELETE等集合操作解决问题时,应优先选择那些方法,只有在真正需要“一行一行”精细操控的时候,才考虑请出游标这个“重武器”。
本文由盈壮于2026-01-23发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://www.haoid.cn/wenda/84693.html
