实验12游标的使用.docx
《实验12游标的使用.docx》由会员分享,可在线阅读,更多相关《实验12游标的使用.docx(13页珍藏版)》请在冰点文库上搜索。
实验12游标的使用
实验十二 游标的使用
姓名:
廖冬凤
学号:
20070721140
专业:
网络工程
班级:
07网络
(1)班
同组人:
无
实验日期:
2009-11-27
【实验目的与要求】
1.掌握使用SQL-92语法和T-SQL扩展声明游标,并理解相关参数含义。
2.掌握游标的使用过程。
【实验内容与步骤】
12.1、声明游标
(1)使用SQL-92语法声明一只进只读游标CUR1:
要求结果集2004年3月18日销售情况。
(2)使用T-SQL扩展声明一滚动动态游标CUR2:
要求结果集为客户信息,并能通过该游标修改客户名称列。
12.2、打开游标
打开CUR2游标。
12.3、读取游标中数据
编写程序,实现依次读取游标CUR2中各行数据。
SQL语句:
DECLARE@客户编号char(6),
@客户名称char(30),
@地区char(10),
@负责人char(8),
@电话char(12)
print'游标结果集中的记录总数为'+cast(@@cursor_rowsasvarchar(10))
fetchnext
fromCUR2
into@客户编号,@客户名称,@地区,@负责人,@电话
while@@fetch_status=0
begin
print'客户编号:
'+cast(@客户编号aschar(6))
+'客户名称:
'+cast(@客户名称aschar(30))
+'地区:
'+cast(@地区aschar(10))
+'负责人:
'+cast(@负责人aschar(8))
+'电话:
'+cast(@电话aschar(12))
fetchnext
fromCUR2
into@客户编号,@客户名称,@地区,@负责人,@电话
end
12.4、关闭游标
关闭CUR2游标。
12.5、释放游标
释放CUR2游标。
【实验练习】
编写程序,用游标实现从CP表中读取产品编号、产品名称和价格,并将价格在1000-3000(不包含1000和3000)之间的产品名称和价格输出。
【分析与回答】
1.什么是游标?
为什么要使用游标?
在数据库中,游标是一个十分重要的概念。
游标提供了一种对从表中检索出的数据进行操作的灵活手段,就本质而言,游标实际上是一种能从包括多条数据记录的结果集中每次提取一条记录的机制。
游标总是与一条T_SQL选择语句相关联因为游标由结果集(可以是零条、一条或由相关的选择语句检索出的多条记录)和结果集中指向特定记录的游标位置组成。
当决定对结果集进行处理时,必须声明一个指向该结果集的游标。
如果曾经用C语言写过对文件进行处理的程序,那么游标就像您打开文件所得到的文件句柄一样,只要文件打开成功,该文件句柄就可代表该文件。
对于游标而言,其道理是相同的。
可见游标能够实现按与传统程序读取平面文件类似的方式处理来自基础表的结果集,从而把表中数据以平面文件的形式呈现给程序。
关系数据库管理系统实质是面向集合的,在MSSQLSERVER中并没有一种描述表中单一记录的表达形式,除非使用where子句来限制只有一条记录被选中。
因此我们必须借助于游标来进行面向单条记录的数据处理。
由此可见,游标允许应用程序对查询语句select返回的行结果集中每一行进行相同或不同的操作,而不是一次对整个结果集进行同一种操作;它还提供对基于游标位置而对表中数据进行删除或更新的能力;而且,正是游标把作为面向集合的数据库管理系统和面向行的程序设计两者联系起来,使两个数据处理方式能够进行沟通。
2.对游标的操作语句有哪些?
分别代表什么含义?
答:
游标种类
MSSQLSERVER支持三种类型的游标:
Transact_SQL游标,API服务器游标和客户游标。
(1)Transact_SQL游标
Transact_SQL游标是由DECLARECURSOR语法定义、主要用在Transact_SQL脚本、存储过程和触发器中。
Transact_SQL游标主要用在服务器上,由从客户端发送给服务器的Transact_SQL语句或是批处理、存储过程、触发器中的Transact_SQL进行管理。
Transact_SQL游标不支持提取数据块或多行数据。
(2)API游标
API游标支持在OLEDB,ODBC以及DB_library中使用游标函数,主要用在服务器上。
每一次客户端应用程序调用API游标函数,MSSQLSEVER的OLEDB提供者、ODBC驱动器或DB_library的动态链接库(DLL)都会将这些客户请求传送给服务器以对API游标进行处理。
(3)客户游标
客户游标主要是当在客户机上缓存结果集时才使用。
在客户游标中,有一个缺省的结果集被用来在客户机上缓存整个结果集。
客户游标仅支持静态游标而非动态游标。
由于服务器游标并不支持所有的Transact-SQL语句或批处理,所以客户游标常常仅被用作服务器游标的辅助。
因为在一般情况下,服务器游标能支持绝大多数的游标操作。
由于API游标和Transact-SQL游标使用在服务器端,所以被称为服务器游标,也被称为后台游标,而客户端游标被称为前台游标。
在本章中我们主要讲述服务器(后台)游标。
selectcount(id)frominfo
select*frominfo
--清除所有记录
truncatetableinfo
declare@iint
set@i=1
while@i<1000000
begin
insertintoinfovalues('Justin'+str(@i),'深圳'+str(@i))
set@i=@i+1
end
游标操作
使用游标有四种基本的步骤:
声明游标、打开游标、提取数据、关闭游标。
声明游标
象使用其它类型的变量一样,使用一个游标之前,首先应当声明它。
游标的声明包括两个部分:
游标的名称;这个游标所用到的SQL语句。
如要声明一个叫作Cus-tomerCursor的游标用以查询地址在北京的客户的姓名、帐号及其余额,您可以编写如下代码:
DECLARECustomerCursorCURSORFOR
SELECTacct_no,name,balance
FROMcustomer
WHEREprovince="北京";
在游标的声明中有一点值得注意的是,如同其它变量的声明一样,声明游标的这一段代码行是不执行的,您不能将debug时的断点设在这一代码行上,也不能用IF...ENDIF语句来声明两个同名的游标,如下列的代码就是错误的。
IFIs_prov="北京"THEN
DECLARECustomerCursorCURSORFOR
SELECTacct_no,name,balance
FROMcustomer
WHEREprovince="北京";
ELSE
DECLARECustomerCursorCURSORFOR
SELECTacct_no,name,balance
FROMcustomer
WHEREprovince〈〉"北京";
ENDIF
打开游标
声明了游标后在作其它操作之前,必须打开它。
打开游标是执行与其相关的一段SQL语句,例如打开上例声明的一个游标,我们只需键入:
OPENCustomerCursor;
由于打开游标是对数据库进行一些SQLSELECT的操作,它将耗费一段时间,主要取决于您使用的系统性能和这条语句的复杂程度。
如果执行的时间较长,可以考虑将屏幕上显示的鼠标改为hourglass。
提取数据
当用OPEN语句打开了游标并在数据库中执行了查询后,您不能立即利用在查询结果集中的数据。
您必须用FETCH语句来取得数据。
一条FETCH语句一次可以将一条记录放入程序员指定的变量中。
事实上,FETCH语句是游标使用的核心。
在DataWindow和DataStore中,执行了Retrieve()函数以后,查询的所有结果全部可以得到;而使用游标,我们只能逐条记录地得到查询结果。
已经声明并打开一个游标后,我们就可以将数据放入任意的变量中。
在FETCH语句中您可以指定游标的名称和目标变量的名称。
如下例:
FETCHCustmerCur-sor
INTO:
ls_acct_no,
:
ls_name,
:
ll_balance;
从语法上讲,上面所述的就是一条合法的取数据的语句,但是一般我们使用游标却还应当包括其它的部分。
正如我们前面所谈到的,游标只能一次从后台数据库中取一条记录,而在多数情况下,我们所想要作的是在数据库中从第一条记录开始提取,一直到结束。
所以我们一般要将游标提取数据的语句放在一个循环体内,直至将结果集中的全部数据提取后,跳出循环圈。
通过检测SQLCA.SQL-CODE的值,可以得知最后一条FETCH语句是否成功。
一般,当SQLCODE值为0时表明一切正常,100表示已经取到了结果集的末尾,而其它值均表明操作出了问题,这样我们可以编写以下的代码:
lb_continue=True
ll_total=0
DOWHILElb_continue
FETCHCustomerCur-sor
INTO:
ls_acct_no,
:
ls_name,
:
ll_balance;
Ifsqlca.sqlcode=0Then
ll_total+=ll_balance
Else
lb_continue=False
EndIf
LOOP
循环体的结构有多种,这里提到的是最常见的一种。
也有的程序员喜爱将一条FETCH语句放在循环体的前面,循环体内再放置另外一条FETCH语句,并检测SQLCA.SQLCODE是否为100。
但是这样做,维护时需同时修改两条FETCH语句,稍麻烦了些。
关闭游标
在游标操作的最后请不要忘记关闭游标,这是一个好的编程习惯,以使系统释放游标占用的资源。
关闭游标的语句很简单:
CLOSECustomerCursor;
使用Where子句子
我们可以动态地定义游标中的Where子句的参数,例如在本例中我们是直接定义了查询省份是北京的记录,但也许在应用中我们要使用一个下拉式列表框,由用户来选择要查询的省份,我们该怎样做呢?
我们在前面曾经提到过,DECLARE语句的作用只是定义一个游标,在OPEN语句中这个游标才会真正地被执行。
了解了这些,我们就可以很方便地实现这样的功能,在DECLARE的Where子句中加入变量作参数,如下所示:
DECLARECustomerCursorCURSORFOR
SELCECTacct_no,name,balance
FROMcustomer
WHEREprovince=:
ls_province;
∥定义ls_province的值
OPENCustomerCursor;
游标的类型
同其它变量一样,我们也可以定义游标的访问类型:
全局、共享、实例或局部,游标变量的命名规范建议也同其它变量一样。
--声明游标
declaremy_cursorcursorkeysetforselect*frominfo
--删除游标资源
deallocatemy_cursor
--打开游标,在游标关闭或删除前都有效
openmy_cursor
--关闭游标
closemy_cursor
--声明局部变量
declare@idint,@namevarchar(20),@addressvarchar(20)
--定位到指定位置的记录
fetchabsolute56488frommy_cursorinto@id,@name,@address
select@idasid,@nameasname,@addressasaddress
--定位到当前记录相对位置记录
fetchrelative-88frommy_cursorinto@id,@name,@address
select@idasid,@nameasname,@addressasaddress
--定位到当前记录前一条
fetchpriorfrommy_cursorinto@id,@name,@address
select@idasid,@nameasname,@addressasaddress
--定位到当前记录后一条
fetchnextfrommy_cursorinto@id,@name,@address
select@idasid,@nameasname,@addressasaddress
--定位到首记录
fetchfirstfrommy_cursorinto@id,@name,@address
select@idasid,@nameasname,@addressasaddress
--定位到尾记录
fetchlastfrommy_cursorinto@id,@name,@address
select@idasid,@nameasname,@addressasaddress
实例:
usedatabase1
declaremy_cursorcursorscrolldynamic
/**//*scroll表示可随意移动游标指针(否则只能向前),dynamic表示可以读写游标(否则游标只读)*/
for
selectproductnamefromproduct
openmy_cursor
declare@pnamesysname
fetchnextfrommy_cursorinto@pname
while(@@fetch_status=0)
begin
print'ProductName:
'+@pname
fetchnextfrommy_cursorinto@pname
end
fetchfirstfrommy_cursorinto@pname
print@pname
/**//*updateproductsetproductname='zzg'wherecurrentofmy_cursor*/
/**//*deletefromproductwherecurrentofmy_cursor*/
closemy_cursor
deallocatemy_cursor
游标的高级技巧
尽管目前基于SQL语句的后台数据库所支持的语言都大致相当,但对游标的支持却有着一些差异,例如对滚动游标支持。
所谓滚动游标,就是程序员可以指定游标向前后任意一个方向滚动。
如在Informix中,您甚至还可以将游标滚向结果集开头或末尾,使用的语句分别是FETCHFIRST,FETCHLAST、FETCHPRIOR和FETCHNEXT。
当程序员用FETCH语句,其缺省是指FETCHNEXT。
由于滚动是在数据库后台实现的,所以滚动游标为用户编程提供了极大的方便。
对游标支持的另一个不同是可修改游标。
上述游标的使用都是指只读游标,而象Oracle、Sybase等数据库却另外支持可作修改的游标。
使用这样的数据库,您可以修改或删除当前游标所在的行。
例如修改当前游标所在行的用户的余额,我们可以如下操作:
UPDATEcustomer
SETbalance=1000
WHERECURRENTofcustomerCursor;
删除当前行的操作如下:
DELETEFROMCustomer
WHERECURRENTOFCustomerCursor;
但是如果您当前使用的数据库是Sybase,您需要修改数据库的参数,将游标可修改的值定为1,才能执行上述操作。
这一赋值在连接数据库的前后进行均可。
SQLCA.DBParm="CursorUpdate=1"
另外一个内容是动态游标,也就是说您可以运行过程中动态地形成游标的SELECT语句。
这同在PowerBuilder中动态地使用嵌入式SQL一样,需要用到DynamicStagin-gArea等数据类型,这已超出了本节的范围。