原理
在数据库开发过程中,我们常常会遇到这样情况,即从某一结果集中逐一地读取一条记录。那么如何解决这种问题呢?
我们知道sql server 并没有提供单一记录的表达形式,除非使用where限制一条语句,因此需要借助游标来进行面向单条记录的数据处理。
游标提供了一种对从表中检索出的数据进行操作的灵活手段,就本质而言,游标实际上是一种能从包括多条数据记录的结果集中每次提取一条记录的机制。由此可见,游标允许应用程序对查询语询select返回的行结果集中每行进行相同或不同的操作,而不是一次对整个结果集进行同-种操作;它还提供对基于游标位置而对表中数据进行删除或更新的能力;而且,正是游标把作为面向集合的数据库管理系统和面向行的程序设计两者联系起来,使两个数据处理方式能够进行沟通。
使用方法
使用游标的基本操作步骤:声明游标、打开游标、提取数据、关闭游标。
1、声明游标
游标的声明包括两个部分:游标的名称、游标用到的select语句。
eg.
declare custCursor CURSOR FOR
select cus_no,name,
yue --余额
from customer
注意点:如同其它变量声明一样,游标声明是不执行的,不能将断点设在这一行代码上,也不能声明两个同名的游标,即便是用if…end if语句。
2、打开游标
声明游标后在做其它操作时必须先打开它,打开游标实际与其相关的sql语句,打开游标代码:
open custCursor ;
3、提取数据
当用 OPEN 语句打开了游标并在数据库中执行了查询后,您不能立即利用在查询结果集中的数据。您必须用 FETCH 语句来取得数据。一条 FETCH 语句一次可以将一条记录放入程序员指定的变量中。事实上,FETCH 语句是游标使用的核心。使用游标,我们只能逐条记录地得到查询结果。
已经声明并打开一个游标后,我们就可以将数据放入任意的变量中。在 FETCH 语句中您可以指定游标的名称和目标变量的名称。如下例:
FETCH custCursor -sor INTO:
ls_cus_no, :ls_name, :ll_yue;
从语法上讲,上面所述的就是一条合法的取数据的语句,但是一般我们使用游标却还应当包括其它的部分。正如我们前面所谈到的,游标只能一次从后台数据库中取一条记录,而在多数情况下,我们所想要作的是在数据库中从第一条记录开始提取,一直到结束。所以我们一般要将游标提取数据的语句放在一个循环体内,直至将结果集中的全部数据提取后,跳出循环圈。通过检测 SQLCA.SQL-CODE 的值,可以得知最后一条 FETCH 语句是否成功。一般,当 SQLCODE值为 0 时表明一切正常,100 表示已经取到了结果集的末尾,而其它值均表明操作出了问题,这样我们可以编写以下的代码:
lb_continue=True
ll_total=0
DO WHILE lb_continue
FETCH custCursor -sor INTOls_cus_no, :ls_name, :ll_yue;
If sqlca.sqlcode=0
Then
ll_total+=ll_balance
Else lb_continue=False
End If
LOOP
4、关闭游标
在游标操作的最后请不要忘记关闭游标,这是一个好的编程习惯,以使系统释放游标占用的资源。关闭游标的语句很简单:
CLOSE custCursor ;
游标的类型 同其它变量一样,我们也可以定义游标的访问类型:全局、共享、实例或局部,游标变量的命名规范建议也同其它变量一样。
声明游标
declare my_cursor cursor keyset for select * from info
删除游标资源
deallocate my_cursor`
打开游标,在游标关闭或删除前都有效
open my_cursor
关闭游标
close my_cursor
声明局部变量
declare @id int,@name varchar(20),@address varchar(20)
定位到指定位置的记录
fetch absolute 56488 from my_cursor into @id,@name,@address select @id as id,@name as name,@address as address
定位到当前记录相对位置记录
fetch relative -88 from my_cursor into @id,@name,@address select @id as id,@name as name,@address as address
定位到当前记录前一条
fetch prior from my_cursor into @id,@name,@address select @id as id,@name as name,@address as address
定位到当前记录后一条
fetch next from my_cursor into @id,@name,@address select @id as id,@name as name,@address as address
定位到首记录
fetch first from my_cursor into @id,@name,@address select @id as id,@name as name,@address as address
定位到尾记录
fetch last from my_cursor into @id,@name,@address select @id as id,@name as name,@address as address
实例:
declare my_cursor cursor scroll dynamic
/*scroll 表示可随意移动游标指针(否则只能向前),dynamic 表示可以读写游标(否则游标只读)*/
for select productname from product
open my_cursor
declare @pname sysname
fetch next