您好!欢迎访问家园网-www.jy.wang!

家园网

SQl Server 中读取游标的一段代码

网络 作者:本站 点击:
DECLARE cursor_goods CURSOR FOR         	/*声明游标*/
  SELECT goods_id,goods_name,store_count FROM goods
  WHERE store_count BETWEEN 500 AND 999  	/*定义游标结果集*/
OPEN cursor_goods                            /*打开游标*/ 
FETCH NEXT FROM cursor_goods               /*执行取数操作*/
WHILE @@fetch_status = 0                  /*判断是否还可以继续取数*/
BEGIN
  FETCH NEXT FROM cursor_goods
END
  CLOSE cursor_goods                        /*关闭游标*/
  DEALLOCATE cursor_goods                  /*释放游标*/

SQL Server 游标代码逐行详解

这是一个标准的 SQL Server 游标操作流程,用于逐行处理查询结果集。让我从整体到细节讲清楚。


一、整体功能概述

这段代码的作用是:

遍历 goods 表中库存量在 500-999 之间的商品,并逐行取出商品信息

注意:代码中 WHILE 循环里只执行了 FETCH没有实际处理数据的语句。实际开发中会在循环内添加业务逻辑。


二、游标的五个标准步骤

text

┌─────────────────────────────────────────────────────────────┐
│  步骤1:DECLARE CURSOR  →  声明游标(定义要查询什么)        │
│         ↓                                                   │
│  步骤2:OPEN            →  打开游标(执行查询,准备取数据)   │
│         ↓                                                   │
│  步骤3:FETCH           →  取一行数据                       │
│         ↓                                                   │
│  步骤4:WHILE 循环      →  重复取数据直到取完               │
│         ↓                                                   │
│  步骤5:CLOSE           →  关闭游标(释放结果集)           │
│         ↓                                                   │
│  步骤6:DEALLOCATE      →  释放游标(删除游标定义)         │
└─────────────────────────────────────────────────────────────┘


三、逐行详细讲解

第1行:DECLARE cursor_goods CURSOR FOR

sql

DECLARE cursor_goods CURSOR FOR

部分含义
DECLARE声明(拉丁语 declarare
cursor_goods游标名称(goods 游标)
CURSOR游标类型
FOR为了(指向后面的 SELECT 语句)

作用:告诉 SQL Server,我要声明一个名叫 cursor_goods 的游标,它要执行的查询是后面的 SELECT 语句。


第2-3行:SELECT ... FROM ... WHERE ...

sql

  SELECT goods_id,goods_name,store_count FROM goods  WHERE store_count BETWEEN 500 AND 999

部分含义
goods_id商品编号
goods_name商品名称
store_count库存数量
FROM goods从商品表查询
WHERE store_count BETWEEN 500 AND 999筛选库存在 500-999 之间的商品

作用:定义游标的结果集——哪些数据可以被逐行遍历。


第4行:OPEN cursor_goods

sql

OPEN cursor_goods

单词词源含义
OPEN古英语 openian打开、开启

作用

  • 执行游标关联的 SELECT 语句

  • 把结果集准备好

  • 游标指针指向第一行之前


第5行:FETCH NEXT FROM cursor_goods

sql

FETCH NEXT FROM cursor_goods

部分含义
FETCH取(古英语 fetian
NEXT下一行
FROM从...
cursor_goods游标名称

作用

  • 从游标中取第一行数据

  • 然后游标指针自动下移

重要:如果想把取出的数据存到变量里,应该这样写:

sql

FETCH NEXT FROM cursor_goods INTO @id, @name, @count


第6行:WHILE @@fetch_status = 0

sql

WHILE @@fetch_status = 0

部分含义
WHILE当...的时候(古英语 hwīl
@@fetch_status系统全局变量,记录上次 FETCH 的状态
= 0等于 0 表示 FETCH 成功取到了数据

作用:只要上次 FETCH 操作成功(还有数据可读),就继续循环。

@@fetch_status 的三种状态

返回值含义
0成功取到一行数据
-1取数据失败(如行已删除)
-2取到的是丢失的行的数据

第7行:BEGIN

sql

BEGIN

作用:标记循环体的开始。


第8行:FETCH NEXT FROM cursor_goods

sql

  FETCH NEXT FROM cursor_goods

作用:取下一行数据,并更新 @@fetch_status

问题:这里没有 INTO 子句,取出的数据没有保存。

本意应该是

sql

  FETCH NEXT FROM cursor_goods INTO @goods_id, @goods_name, @store_count


第9行:END

sql

END

作用:标记循环体的结束。程序会跳回 WHILE 继续判断。


第10行:CLOSE cursor_goods

sql

CLOSE cursor_goods

单词词源含义
CLOSE拉丁语 clausus关闭

作用

  • 关闭游标

  • 释放结果集占用的内存

  • 游标定义还在,可以重新 OPEN


第11行:DEALLOCATE cursor_goods

sql

DEALLOCATE cursor_goods

单词词源含义
DEALLOCATEde-(移除)+ allocate(分配)释放、解除分配

作用

  • 彻底删除游标定义

  • 释放所有相关资源

  • 之后不能再 OPEN


四、完整的正确写法示例

sql

-- 声明变量存放取出的数据DECLARE @goods_id INT, @goods_name NVARCHAR(50), @store_count INT-- 1. 声明游标DECLARE cursor_goods CURSOR FOR
  SELECT goods_id, goods_name, store_count 
  FROM goods  WHERE store_count BETWEEN 500 AND 999-- 2. 打开游标OPEN cursor_goods-- 3. 取第一行数据FETCH NEXT FROM cursor_goods INTO @goods_id, @goods_name, @store_count-- 4. 循环处理WHILE @@FETCH_STATUS = 0BEGIN
    -- 在这里处理每一行数据
    PRINT '商品:' + @goods_name + ',库存:' + CAST(@store_count AS VARCHAR)
    
    -- 取下一行
    FETCH NEXT FROM cursor_goods INTO @goods_id, @goods_name, @store_countEND-- 5. 关闭游标CLOSE cursor_goods-- 6. 释放游标DEALLOCATE cursor_goods


五、各步骤状态变化图

text

┌─────────────────────────────────────────────────────────────┐
│  DECLARE                                                     │
│  cursor_goods 定义好了,但没有数据                           │
├─────────────────────────────────────────────────────────────┤
│  OPEN                                                        │
│  执行查询,结果集:第1行、第2行、第3行...                    │
│  指针指向 [第1行之前]                                        │
├─────────────────────────────────────────────────────────────┤
│  FETCH INTO                                                  │
│  取第1行 → 变量得到值 → 指针指向 [第1行和第2行之间]          │
│  @@FETCH_STATUS = 0(成功)                                 │
├─────────────────────────────────────────────────────────────┤
│  WHILE 循环                                                  │
│  处理第1行 → FETCH 第2行 → 处理第2行 → ...                   │
│  取完最后一行后,再 FETCH 时 @@FETCH_STATUS ≠ 0 → 退出循环   │
├─────────────────────────────────────────────────────────────┤
│  CLOSE                                                       │
│  游标关闭,结果集释放                                        │
├─────────────────────────────────────────────────────────────┤
│  DEALLOCATE                                                  │
│  游标定义删除,彻底清理                                       │
└─────────────────────────────────────────────────────────────┘


六、为什么原代码有个细节问题?

原代码:

sql

FETCH NEXT FROM cursor_goods

问题:没有 INTO 子句,取出的数据没有地方存放

正确写法

sql

FETCH NEXT FROM cursor_goods INTO @变量1, @变量2, @变量3


七、词源总结

关键字词源含义
CURSOR拉丁语 cursor(奔跑者)游标(在数据上"跑")
DECLARE拉丁语 declarare声明
OPEN古英语 openian打开
FETCH古英语 fetian取来
CLOSE拉丁语 clausus关闭
DEALLOCATEde- + allocate释放、解除分配

八、总结

步骤代码作用
1DECLARE ... CURSOR FOR声明游标,定义要遍历的数据集
2OPEN打开游标,执行查询
3FETCH NEXT取第一行数据
4WHILE @@FETCH_STATUS = 0判断是否还有数据
5BEGIN...END循环体(处理数据 + 取下一行)
6CLOSE关闭游标,释放结果集
7DEALLOCATE释放游标定义,彻底清理

一句话总结:游标的本质是一个数据遍历器——先 DECLARE 定义要取什么数据,再 OPEN 打开它,然后 FETCH 一行一行地取,用 WHILE 循环处理每一行,最后 CLOSE 和 DEALLOCATE 释放资源。这是一种逐行处理而非批量处理的方式。

⚠️ 性能提示:游标在处理大量数据时效率较低,能用集合操作(UPDATEDELETEINSERT...SELECT)时尽量不要用游标。只有在需要逐行进行复杂业务逻辑时才使用游标


标签: