数据库游标

来源:互联网 发布:网络出版许可证查询 编辑:程序博客网 时间:2024/06/05 18:23

在数据库开发过程中,当你检索的数据只是一条记录时,你所编写的事务语句代码往往使用SELECT INSERT 语句。但是我们常常会遇到这样情况,即从某一结果集中逐一地读取一条记录。那么如何解决这种问题呢?游标为我们提供了一种极为优秀的解决方案。

1.游标和游标的优点
                
   在数据库中,游标是一个十分重要的概念。游标提供了一种对从表中检索出的数据进行操作的灵活手段,就本质而言,游标实际上是一种能从包括多条数据记录的结果集中每次提取一条记录的机制。游标总是与一条SQL  选择语句相关联因为游标由结果集(可以是零条、一条或由相关的选择语句检索出的多条记录)和结果集中指向特定记录的游标位置组成。当决定对结果集进行处理时,必须声明一个指向该结果集的游标。如果曾经用 C 语言写过对文件进行处理的程序,那么游标就像您打开文件所得到的文件句柄一样,只要文件打开成功,该文件句柄就可代表该文件。对于游标而言,其道理是相同的。可见游标能够实现按与传统程序读取平面文件类似的方式处理来自基础表的结果集,从而把表中数据以平面文件的形式呈现给程序。

   我们知道关系数据库管理系统实质是面向集合的,在MS SQL SERVER 中并没有一种描述表中单一记录的表达形式,除非使用where  子句来限制只有一条记录被选中。因此我们必须借助于游标来进行面向单条记录的数据处理。由此可见,游标允许应用程序对查询语句select  返回的行结果集中每一行进行相同或不同的操作,而不是一次对整个结果集进行同一种操作;它还提供对基于游标位置而对表中数据进行删除或更新的能力;而且,正是游标把作为面向集合的数据库管理系统和面向行的程序设计两者联系起来,使两个数据处理方式能够进行沟通。

2. 游标种类


   MS SQL SERVER 支持三种类型的游标:Transact_SQL 游标,API 服务器游标和客户游标。
   (1) Transact_SQL 游标
         Transact_SQL 游标是由DECLARE CURSOR 语法定义、主要用在Transact_SQL  脚本、存储过程和触发器中。Transact_SQL 游标主要用在服务器上,由从客户端发送给服务器的Transact_SQL 语句或是批处理、存储过程、触发器中的Transact_SQL 进行管理。 Transact_SQL 游标不支持提取数据块或多行数据。
   (2) API 游标
         API 游标支持在OLE DB, ODBC 以及DB_library 中使用游标函数,主要用在服务器上。每一次客户端应用程序调用API 游标函数,MS SQL SEVER 的OLE DB 提供者、ODBC驱动器或DB_library 的动态链接库(DLL) 都会将这些客户请求传送给服务器以对API游标进行处理。
   (3) 客户游标
         客户游标主要是当在客户机上缓存结果集时才使用。在客户游标中,有一个缺省的结果集被用来在客户机上缓存整个结果集。客户游标仅支持静态游标而非动态游标。由于服务器游标并不支持所有的Transact-SQL  语句或批处理,所以客户游标常常仅被用作服务器游标的辅助。因为在一般情况下,服务器游标能支持绝大多数的游标操作。由于API 游标和Transact-SQL  游标使用在服务器端,所以被称为服务器游标,也被称为后台游标,而客户端游标被称为前台游标。

游标提供了一种对从表中检索出的数据进行操作的灵活手段,就本质而言,游标实际上是一种能从包括多条数据记录的结果集中每次提取一条记录的机制。游标总是与一条T_SQL 选择语句相关联因为游标由结果集(可以是零条、一条或由相关的选择语句检索出的多条记录)和结果集中指向特定记录的游标位置组成。当决定对结果集进行处理时,必须声明一个指向该结果集的游标。

使用游标有四种基本的步骤:声明游标、打开游标、提取数据、关闭游标。

1.声明游标

同其它变量一样,我们也可以定义游标的访问类型:全局、共享、实例或局部,游标变量的命名规范建议也同其它变量一样。 declare my_cursor cursor keyset for select * from info

DECLARE CustomerCursor CURSOR FOR
SELECT acct_no,name,balance FROM customer WHERE province="北京";

2.打开游标
OPEN CustomerCursor;

3.提取数据
FETCH语句来取得数据。一条FETCH语句一次可以将一条记录放入程序员指定的变量中。已经声明并打开一个游标后,我们就可以将数据放入任意的变量中。在FETCH语句中您可以指定游标的名称和目标变量的名称。

--声明局部变量
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 MyCursor CURSOR SCROLL FOR ·· (FAST_FORWARD :只进游标 ; SCROLL: 滚动游标 )

示例:

DECLARE MyCursor CURSOR SCROLL FOR SELECT * FROM Test1

DECLARE @ROW1 int,@ROW2 char(10),@ROW3 char(10),@ROW4 char(10)

OPEN MyCursor

FETCH next FROM MyCursor INTO @ROW1, @ROW2, @ROW3, @ROW4

WHILE (@@fetch_status =0)
BEGIN

INSERT INTO Test1(id, a, b, c)
VALUES (@ROW1, @ROW2, @ROW3, @ROW4)

FETCH next FROM MyCursor INTO @ROW1, @ROW2, @ROW3, @ROW4

END
CLOSE MyCursor
DEALLOCATE MyCursor

(示例是将Test1表中的数据复制一次!)

(@@fetch_status 返回被 fetch 语句执行的最后游标的状态,而不是任何当前被连接打开的游标的状态。0 fetch 语句成功;-1 fetch语句失败或此行不在结果集中;-2 被提取的行不存在;所以使用@@fetch_status=0判断是否游标到了最后一行

高级应用

修改当前游标所在行的信息,我们可以如下操作:
UPDATE table1
SET balance=1000
WHERE CURRENT of yourCursor;
删除当前行的操作如下:
DELETE FROM table1
WHERE CURRENT OF yourCursor;

此时声明游标的时候:declare my_cursor cursor scroll dynamic for ···
scroll表示可随意移动游标指针(否则只能向前),dynamic表示可以读写游标(否则游标只读)


原创粉丝点击