游标的应用与初探
[选项参数]
FOR
[FOR UPDATE [ OF 字段名1 [,…] ]
FETCH
[ [ NEXT | PRIOR | FIRST | LAST
| ABSOLUTE { n | @nvar }
| RELATIVE { n | @nvar } ]
FROM ]
{ { [ GLOBAL ] cursor_name } |
@cursor_variable_name }
[ INTO @variable_name [ ,...n ] ]
UPDATE 表名
SET 列名1 = {表达式1 | NULL (select语句) } [, …]
WHERE CURRENT OF 游标名
DELETE FROM 表名
WHERE CURRENT OF 游标名
游标的应用重点可表现在 2 个方面:
1)使用游标从结果集中检索数据,以实现对数据的逐行查看,也就是平时经常遇到的一种操作———遍历。
2)使用游标可以对结果集中的数据进行更新或删除。改变游标中的数据,自然会影响到数据库中基础表的数据,若要使游标中的数据不致发生修改,则可以在声明游标时添加Insensitive 选项。
在此,将以某个学校学费收缴管理系统中的学校收费数据库为背景,研究给出 2 个具体实例来阐释说明 SQL Server中游标的使用方法和应用实现
利用游标遍历从 wbf 数据库的 wbf_UserTestInfo(学生信息表)和 wbf_UserTestSf(专业收费表)中显示所有文学院学生的专业代码(zydm)、专业名称(zymc)、隶属院系(lsyx)、学号(xh)和姓名(xm),并以报表的形式提供结果输出。当前数据库的基础表 wbf_UserTestInfo 和 wbf_UserTestSf,表的结构可如表 1 和表 2,字段 zydm、zymc 和 lsyx 来源于表 2,字段 zydm、xh 和 xm来源于表 1。2 张表将通过公共字段 zydm 建立连接。
--测试表wbf_UserTestInfo
CREATE TABLE wbf_UserTestInfo
(
rxnf INT, --入学年份
xh char(10), --学号
xb varchar(20), --性别
xm char(8), --姓名
ksh INT, --考生号
sfzh char(18), --身份证号
zydm char(5), --专业代码
zsbz varchar(20), --住宿标准
)
--测试表wbf_UserTestSf
CREATE TABLE wbf_UserTestSf
(
zydm char(5), --专业代码
zymc varchar(50), --专业名称
lsyx varchar(50), --隶属院系
pscc varchar(20), --培养层次
xxnx INT, --学习年限
zsbz INT, --学费标准
jcfbz INT, --教材费标准
)
--插入数据到测试表wbf_UserTestInfo
INSERT wbf_UserTestInfo
VALUES (2016,1613030102,'女','邬必芬',16060,460003199803056824,1613030,1200)
--插入数据到测试表wbf_UserTestSf
use wbf
go
INSERT wbf_UserTestSf
VALUES (1613030,'信管1602','信息与安全工程学院','本科生',4,8300,5300)
--通过游标实现数据遍历的关键代码如下:
use wbf
go
DECLARE @zydm char(10),@zymc varchar(50),@lsyx varchar(50),@xh char(10),@xm char(8)--声明变量
DECLARE cur_college CURSOR FOR --声明游标
SELECT wbf_UserTestSf.zydm,zymc,lsyx,xh,xm
FROM wbf_UserTestInfo,wbf_UserTestSf
WHERE wbf_UserTestInfo.zydm=wbf_UserTestSf.zydm and lsyx='信息与安全工程学院'
FOR READ ONLY
OPEN cur_college--打开游标
FETCH NEXT FROM cur_college INTO @zydm,@zymc,@lsyx,@xh,@xm --提取游标结果集中的数据,并将字段值存放到相应的游标变量中
PRINT SPACE(25)+'信息与安全工程学院的学生名单'
PRINT''
WHILE @@FETCH_STATUS=0--检查@ @ FETCH_STATUS,确定游标读取数据是否正确,若正确则循环遍历结果集中的数据
BEGIN
PRINT '专业代码:'+ @zydm+' 专业名称:'+@zymc+' 隶属院系:'+@lsyx+' 学号:'+@xh+' 姓名:'+@xm--输出数据
FETCH NEXT FROM cur_college INTO @zydm,@zymc,@lsyx,@xh,@xm --读取下一条数据
END
CLOSE cur_college --关闭游标
DEALLOCATE cur_college --释放游标
在上述代码中,主要是通过两个 fetch 和一个 while 语句的结合使用来完成游标的遍历。第一次使用 fetch 语句获取第一条记录的内容,然后在循环中再次使用 fetch 语句来获取
下一条记录的内容,直至游标溢出循环才真正结束。此外,还有一种方式也可以实现游标的遍历。
--程序代码如下:
DECLARE @zydm char(10),@zymc varchar(50),@lsyx varchar(50),@xh char(10),@xm char(8)--声明变量
WHILE 1=1 --条件为永真
BEGIN
FETCH NEXT FROM cur_college INTO @zydm,@zymc,@lsyx,@xh,@xm
IF @@FETCH_STATUS=0 --若读取数据正确则进行相关操作
ELSE
BREAK --游标溢出即遍历结束后跳出循环
END
相对于第一种方式而言,第二种方式主要是通过永真的循环只使用一次 fetch 语句来实现游标的遍历。本节研究中提出的这 2 种方式在执行遍历操作上,均展现有良好效能。但从某种程度上来讲,第一种方式更加简洁、直观。
利用游标将数据表wbf_UserTestInfo 中第 3 位同学的入学年份(rxnf)改为 2012 年(这里只显示 wbf_UserTestInfo 表中的 rxnf、xh、xm、xb 和 sfz 字段)。
--关键代码如下:
DECLARE cur_xg SCROLL CURSOR FOR
SELECT rxnf,xh,xm,xb,sfz from wbf_UserTestInfo
FOR UPDATE OF rxnf -- 定义表中需要修改的数据列
OPEN cur_xg
FETCH ABSOLUTE 3 FROM cur_xg -- 返回第 3 行并将其变为当前行
UPDATE wbf_UserTestInfo SET rxnf=2012 -- 更新当前行的列值
WHERE CURRENT OF cur_xg -- 当前游标指针所指的当前行数据
CLOSE cur_xg
DEALLOCATE cur_xg
这里需要注意的是,游标的第二种应用是一种不规范的更新数据的途径,很容易造成数据的不一致,因此通常状况下并不选用游标来设计更新数据表中的数据。另外,还需提及的就是,本文实所用的数据表均基于wbf_UserTestSf(学校收费数据库)中的 2 个表,分别是:
wbf_UserTestInfo(rxnf,xh,xm,xb,ksh,sfz,zydm,zsbz)
wbf_UserTestSf(zydm,zymc,lsyx,pycc,xxnx,xfbz,jcfbz)
测试总结:
SQL Server 中的游标在原理上具有 C 语言指针一样的语言结构,相应地则设计提供了一种在服务器内部处理结果集的方法。使用游标可以通过遍历操作逐一地从结果集中实现数据读取,也可以对结果集中某些数据重点加设更新或删除的操作。本文以学校收费数据库为背景并结合具体的实例来阐述游标的使用,游标可以面向结果集中的每一行进行相同或不同的操作,这不仅提升了 SQL 语句处理复杂查询的能力,而且还降低了系统开销和潜在的阻隔情况,在一定程度上解决了许多应用程序不能把整个结果集作为一个单元来处理的问题。