第14章 游标

第14章 游标

在SQL中,游标是一个重要的概念,它提供了能从包括多条数据记录的结果集中每次提取一条记录的机制,使得用户能够灵活地处理SQL操作经常返回的结果集。本章将讲解与游标相关的一些内容。

14.1 理解游标
在关系数据库中,对数据的操作会对整个行集产生影响,如常用的SELECT查询语句,其返回结果是一个结果集,但是用户往往需要从结果集中逐一地读取一条记录,要解决这个问题可以通过游标来实现。

14.1.1 游标概述
游标是从数据表中提取出来的数据,是一种能从包括多条数据记录的结果集中每次提取一条记录的机制,以临时表的形式存放在内存中。游标向数据库发送查询,得到一个记录集,但是游标一次只返回一个记录行,而不是大批地返回行。
游标是由结果集(可以是零条、一条或由相关的SELECT语句检索出的多条记录)和结果集中指向特定记录的游标位置组成,游标充当指针的作用。尽管游标能够遍历查询结果中的所有行,但它一次只指向一行。
游标通过以下方式扩展结果处理:

  • 允许定位在结果集的特定行。
  • 从结果集的当前位置检索一行或多行。
  • 支持对结果集中当前位置的行进行数据修改。
  • 为由其他用户对显示在结果集中的数据库数据所做的更改提供不同级别的可见性支持。

简单来讲,数据库的游标是类似于C语言指针一样的语言结构。通常情况下,数据库执行的大多数SQL命令都是同时处理集合内部的所有数据。但是,有时侯用户也需要对这些数据集合中的每一行进行操作。在没有游标的情况下,这种工作不得不放到数据库前端,用高级语言来实现。这将导致不必要的数据传输,从而延长执行的时间。通过使用游标,可以在服务器端有效地解决这个问题。

14.1.2 游标的作用及其应用
游标的一个最常见的作用就是保存查询的结果,以便以后使用。游标的结果集是由SELECT语句产生,如果处理过程需要重复使用一个记录集,那么就需要创建一次游标来完成相应的操作。
使用游标的具体作用有以下几点:

  • 使用游标可以选择一组数据。
  • 可以在记录集上滚动游标。
  • 可以检查游标指向的每一数据。
  • 可以用局部变量和游标的组合来分别检查每个记录,并在转移到下一个记录之前,进行所需的任何操作。

14.2 游标的简单应用
使用游标通常按照声明游标、打开游标、使用游标操作数据和关闭游标的顺序进行。本节中主要讲解一下游标的创建、打开、检索、关闭及使用等方面的内容。

14.2.1 创建游标
在SQL中,使用DECLARE CURSOR语句创建游标,使用DECLARE CURSOR语句不仅可以指定用户或者应用程序使用游标时采取的动作,而且还可以指定存储于游标中的结果集。
【语法说明】
在SQL中,创建游标的语法格式如下所示。

DECLARE cursor_name[INSENSITIVE][SCROLL] CURSOR
FOR select_statement
[FOR {READ ONLY | UPDATE[OF column_name[,…n]]}]

代码中的各项参数说明如下所示。

  • cursor_name:指游标的名称。
  • INSENSITIVE:表示在定义游标时将在tempdb数据库中创建一个临时数据表,用于存储与该游标使用的数据。
  • SCROLL:表示所有的提取操作(如FIRST、LAST、NEXT、RELATIVE和ABSOLUTE等)都可用。如果不使用该关键字,那么只能进行NEXT提取操作。
  • select_statement:表示定义结果集中的SELECT语句。但是,在游标中不能使用COMPUTE、COMPU-TE BY、FOR BROWSE和INTO等关键字。
  • READ ONLY:表示指定的游标为只读游标。READ ONLY参数将禁止UPDATE或DELETE语句通过游标修改基本表中的数据。
  • UPDATE[OF column_name[,…n]]:表示定义游标内可更新的列。如果指定OF参数,则只能允许修改所列出的列。如果在UPDATE中未指定列的列表,则可以更新所有列的数据。

【上机实战】
创建游标Ygxx_Cursor,其指向的结果集为员工信息表(tb_ygxx)中货物编号、姓名、性别和年龄信息,并在结果集中以员工编号进行升序排序,其实现的代码如下所示。

DECLARE Ygxx_Cursor SCROLL CURSOR
FOR
SELECT 编号,姓名,性别,年龄
FROM tb_ygxx
ORDER BY 编号

代码执行以后,游标创建完成。
14.2.2 打开游标
游标创建之后需要将其打开才能够被使用。打开游标的操作非常的简单,只需在OPEN关键字后面加上游标的名字即可。
【语法说明】
打开游标的语法结构如下所示。

OPEN cursor_name

代码中的cursor_name表示要打开游标的名称。
【上机实战】
打开在前面章节中创建的游标Ygxx_Cursor。

OPEN Ygxx_Cursor

代码执行以后,游标被打开。
14.2.3 关闭游标
在SQL中使用CLOSE语句关闭游标。
【语法说明】
关闭游标的语法结构如下所示。

CLOSE cursor_name

代码中的cursor_name表示的是要关闭游标的名称。
说明:在关闭游标之后,就不能够检索结果集中的数据行信息,只有通过OPEN语句再次打开游标时,才能够执行检索操作。
【上机实战】
关闭前面章节中创建的游标Ygxx_Cursor。

CLOSE Ygxx_Cursor

代码执行以后,游标被关闭。
14.3.4 释放游标
通过CLOSE语句只能够关闭游标,而不能释放游标所占用的资源。如果想再次使用游标,可以再次通过OPEN语句打开游标。如果想释放游标所占用的资源,必须使用释放游标的语句将游标资源释放。
在SQL Server中,使用DEALLOCATE命令释放游标所占用的系统资源。使用DEALLOCATE命令可以将游标作为对象连同游标中的数据一起从数据库中删除。
在使用DEALLOCATE命令释放游标之后,就不可以再次通过OPEN语句打开游标了。如果想再次打开游标,必须通过DECLARE CUSOR语句重新创建游标。
【语法说明】
使用DEALLOCATE命令的语法格式如下所示。

DEALLOCATE cursor_name

代码中的cursor_name表示游标的名称。
【上机实战】
释放在前面章节中创建的游标Ygxx_Cursor。

DEALLOCATE Ygxx_Cursor

代码执行以后,游标被释放。

注意:DEALLOCATE命令包括了关闭游标和释放游标两个动作,因此,在使用DEALLOCATE命令释放之前,不必再使用CLOSE命令关闭游标。

14.3.5 使用游标
使用游标的操作步骤如下所示。
(1)创建游标
创建游标也称为声明游标,是指在使用游标之前要先定义游标的名称以及一些可调用的查询表达式。
(2)打开游标
创建游标之后,游标还不能够被调用,若想被调用,还必须得把游标打开。
(3)检索数据
每次检索出(通过FETCH)数据记录中的一行,直到记录集中的最后一行记录。
(4)关闭及释放游标
游标在使用完成之后要将其关闭,以便释放游标所占用的系统资源。

14.2.6 检索游标
当游标被打开之后,便可以从游标中逐行地检索数据以进行相应地处理。在SQL中使用FETCH语句检索游标中的数据,FETCH语句用于查找数据集中的单行数据,并将其提取的单个值传给主变量。
【语法说明】
使用FETCH语句检索游标中数据的语法结构如下所示。

FETCH [ [fetch_orient] FROM ]
Cursor_name INTO host_var

代码中的各项参数说明如下所示。

  • Cursor_name:表示为游标的名称。
  • host_var:表示接收游标检索行值的主变量。
  • fetch_orient:表示游标的定位选项,当FETCH语句中有定位选项时,必须加上FROM关键字。

在SQL中,游标有6种定位选项,用来确定从游标的查询结果中选择哪一行。这些选项列举如下所示:

  • FIRST:返回游标中第一行。
  • LAST:返回游标中的最后一行。
  • NEXT:返回结果集中当前行的下一行。
  • PRIOR:返回结果集中当前行的前一行。
  • ABSOLUTEn:移动到结果集中的第n行。如果n为正数,DBMS从游标的结果集的第一行算起移到第n行;如果n是负数,DBMS则从结果集最后一行算起,移到第n行。
  • RELATIVEn:从游标指针的当前位置移动n行。若n为正数,则读取游标当前位置起向后的第n行数据。如果n为负数,则读取游标当前位置起向前的第n行数据。

【上机实战】
从游标Ygxx_Cursor中检索员工编号从小到大排列的包括货物编号、姓名、性别和年龄的前3行数据信息。

OPEN Ygxx_Cursor  /* 打开游标 */
DECLARE @gNo INT,@gName CHAR(10),@sex CHAR(2),@age INT
/* 显示游标中的第1条记录 */
FETCH FIRST FROM Ygxx_Cursor INTO @gNo,@gName,@sex,@age
PRINT '编号:' + CAST(@gNo AS CHAR(6)) +'姓名:'+ @gName + '性别:'+ CAST(@sex AS CHAR(2)) + ' 年龄:'+ CAST(@age as char(4))
/* 显示游标中的下1条记录 */
FETCH NEXT FROM Ygxx_Cursor INTO @gNo,@gName,@sex,@age
PRINT '编号:' + CAST(@gNo AS CHAR(6)) +'姓名:'+ @gName + '性别:'+ CAST(@sex AS CHAR(2)) + ' 年龄:'+ CAST(@age as char(4))
FETCH NEXT FROM Ygxx_Cursor INTO @gNo,@gName,@sex,@age
PRINT '编号:' + CAST(@gNo AS CHAR(6)) +'姓名:'+ @gName + '性别:'+ CAST(@sex AS CHAR(2)) + ' 年龄:'+ CAST(@age as char(4))
CLOSE Ygxx_Cursor /* 关闭游标 */

代码执行以后,输出结果如图14.1所示。
在这里插入图片描述
图14.1 使用FETCH语句检索游标
下面分析一下该示例的实现过程。

  • 首先,通过OPEN语句打开游标Ygxx_Cursor,然后定义4个变量,分别用于存储每次游标检索出的行数据值(包括编号、姓名、性别和年龄)。
  • 通过FETCH语句检索数据。首先,DBMS通过FETCH
    FIRST语句将游标指针移动到结果集中的第一条记录,将该记录的4列数据信息分别赋值到INTO语句指定的4个临时变量当中。
  • 使用FETCH
    NEXT语句显示其下一条数据信息,将游标指针指向下一行记录,获得第2行记录信息,再次将该记录的4列数据信息分别赋值到INTO语句指定的4个临时变量当中。再次使用FETCH
    NEXT语句,用同样的方法获得第3条记录信息。

示例中游标指针的滚动如图15.2所示。
在这里插入图片描述
图14.2 Goods_Cursor游标指针的滚动示意图
当执行完毕后,使用CLOSE语句关闭游标。

说明:上述示例在Sql Server数据库中实现。

14.3 Sql Server中游标应用
在SQL Server中,除了可以使用SQL-92游标语法定义的标准游标语法创建和使用游标外,Transact-SQL还提供了一种扩展游标语法,本节将详细介绍该种游标的创建和使用,以及游标的管理和维护等操作。

14.3.1 UPDATE可更新游标
如果创建游标的DECLARE CURSOR语句中不包含READ ONLY选项,就可以使用定位UPDATE语句更新源表中的数据记录。
标准UPDATE语句中的WHERE子句,用于检索一列或多列要修改数据值的行;而在定位的UPDATE语句的WHERE子句中,检索条件基于游标的当前行指针的位置。
【语法说明】
用于UPDATE操作的可更新游标的语法格式如下所示。

UPDATE table_name
SET column1=value1,column2=value2,…,columnN=valueN
WHERE CURRENT OF Cursor_name

代码中的table_name表示要更新数据表的名称,column=value表示要更新数据表的列名称,Cursor_name表示游标的名称。
【上机实战】
创建可更新游标Update_Cursor,该游标返回员工信息表(tb_ygxx)中所有年龄高于25岁的结果集。然后再通过基于游标定位的UPDATE语句,从员工信息表(tb_ygxx)中将年龄高于25岁的数据记录,将联系方式设置为“长春市”,为了便于比较,现将员工信息表(tb_ygxx)中的数据信息显示出来。

select * from tb_ygxx

代码执行以后,其执行结果如图14.3所示。
在这里插入图片描述
图14.3 员工信息表(tb_ygxx)中的数据信息
通过UPDATE操作实现可更新游标的实现代码如下所示。

/* 创建游标 */
DECLARE Update_Cursor CURSOR
FOR
SELECT 联系地址 FROM tb_ygxx
WHERE 年龄>25
FOR UPDATE /* 设置游标为可更新的 */
DECLARE @age int,@lldz char(12)   /* 定义游标变量 */
SELECT @lldz=联系地址
FROM tb_ygxx
WHERE 年龄>25
/* 打开并执行游标 */
OPEN Update_Cursor
FETCH FROM  Update_Cursor
INTO @lldz
WHILE @@FETCH_STATUS=0
BEGIN
  UPDATE tb_ygxx SET 联系地址='长春市'
  WHERE CURRENT OF Update_Cursor
  FETCH FROM Update_Cursor INTO @lldz
END 
CLOSE Update_Cursor

代码执行以后,操作完成。此时查看员工信息表(tb_ygxx)中的数据信息如图14.4所示。
在这里插入图片描述
图14.4 执行可更新游标操作之后员工信息表(tb_ygxx)中的数据信息
14.3.2 DELETE可更新游标
如果游标是可更新的,也可以用游标从游标数据的源表中删除行。基于游标的DELETE语句称为定位DELETE语句。
【语法说明】
DELETE可更新游标的实现语句结构如下所示。

DELETE FROM table_name
WHERE CURRENT OF cursor_name

代码中的table_name表示删除记录表的名称,cursor_name表示游标的名称。
【上机实战】
创建可更新游标delete_Cursor,该游标返回员工信息表(tb_ygxx)中所有员工年龄高于25岁的结果集。然后再通过基于游标定位的DELETE语句,从员工信息表(tb_ygxx)中将员工年龄高于25岁记录集中的第1条记录和第3条记录删除,其实现的代码如下所示。

/* 创建游标*/
DECLARE delete_Cursor CURSOR
FOR
SELECT 年龄 FROM tb_ygxx
WHERE 年龄>25
FOR UPDATE /* 设置游标为可更新的*/
/* 打开并执行游标*/
OPEN delete_Cursor
FETCH FROM  delete_Cursor
DELETE FROM tb_ygxx  /* 删除第1行记录*/
WHERE CURRENT OF delete_Cursor
FETCH FROM  delete_Cursor
FETCH FROM  delete_Cursor
DELETE FROM tb_ygxx  /* 删除第3行记录*/
WHERE CURRENT OF delete_Cursor
CLOSE delete_Cursor

代码运行之后,操作完成。此时查看员工信息表(tb_ygxx)中的数据信息如图14.5所示。
在这里插入图片描述
图14.5 执行可更新游标操作之后员工信息表(tb_ygxx)中的数据信息
说明:执行DELETE可更新游标之前员工信息表(tb_ygxx)中的数据信息,请参见图14.4。
14.3.3 @@CURSOR_ROWS全局变量的应用
当游标被打开后,可以使用全局变量@@CURSOR_ROWS来记录游标内数据的行数。全局变量@@CURSOR_ROWS的返回值共有4个,其具体的含义如下所示。

  • -m:表示从源表向游标读入数据的处理仍在进行,m表示当前在游标中的数据行数。
  • -1:表示该游标是一个动态游标。
  • 0:表示游标已被关闭。
  • n:表示游标中已有数据记录的行数,此时从源表读入数据已经结束。

如果在创建游标时,带有SCROLL或INSENSITIVE选项,则@@CURSOR_ROWS的值为正数,该值就是游标内记录的行数;如果不带有这两个选项,则该游标中只有一条记录,@@CURSOR_ROWS的值为-1。
【上机实战】
创建一个游标Nums_Cursor,返回员工信息表(tb_ygxx)中所有女员工的结果集。同时使用全局变量@@CURSOR_ROWS输出所有记录的条数,其实现的代码如下所示。

/* 创建游标*/
DECLARE nums_Cursor SCROLL CURSOR
FOR
SELECT 编号,姓名,性别,年龄 FROM tb_ygxx /* 定义结果集*/
WHERE 性别='女'
/* 打开并执行游标*/
OPEN nums_Cursor
PRINT '女员工的数据为:' + CAST(@@CURSOR_ROWS AS VARCHAR(4)) + '条'
CLOSE nums_Cursor

代码执行以后,其执行结果如图14.6所示。
在这里插入图片描述
图14.6 @@CURSOR_ROWS全局变量的应用示例
注意:在使用@@CURSOR_ROWS全局变量之前,必须先打开游标。

14.3.4 @@FETCH_STATUS全局变量的应用
在使用OPEN命令打开游标的前提下,可以使用FETCH命令读取游标中的数据,并将其存放在事先定义好的变量当中。在SQL Server当中,可以使用全局变量@@FETCH_STATUS检测最近执行的FETCH语句的执行状态。
@@FETCH_STATUS语句有3个不同的返回值,其具体说明如下所示。

  • 0:表示FETCH命令被执行成功。
  • -1:表示行数据超过游标数据结果集的范围。或者FETCH命令执行失败。
  • 2:表示所读取的数据已经不存在。

【上机实战】
将前面章节中创建的游标nums_Cursor中的所有信息显示出来,其实现的代码如下所示。

/* 打开并执行游标*/
OPEN nums_Cursor
/* 定义变量*/
DECLARE @ST_ID varchar(10),@ST_NAME varchar(10),@ST_SEX varchar(10),@ST_AGE INT
FETCH FROM nums_Cursor  
INTO @ST_ID,@ST_NAME,@ST_SEX,@ST_AGE
/* 如果FETCH语句执行成功,则进入循环*/
WHILE @@FETCH_STATUS=0 
BEGIN
  PRINT '编号:'+ @ST_ID + '姓名:'+ @ST_NAME + '性别:' + @ST_SEX + '年龄:' + CAST(@ST_AGE AS char(10))
FETCH FROM NUMS_Cursor
INTO @ST_ID,@ST_NAME,@ST_SEX,@ST_AGE
END 
/* 关闭游标*/
CLOSE nums_Cursor

代码执行以后,其执行结果如图14.7所示。
在这里插入图片描述
图14.7 @@FETCH_STATUS全局变量的应用示例

14.3.5 Sql Server中的游标管理
通过系统过程可以对游标进行管理。管理游标的系统过程及其功能如下所示。

  • Sp_describe_cursor:用于显示游标的属性。
  • Sp_cursor_list:用于显示当前作用域内的游标及其属性。
  • Sp_describe_cursor_tables:用于显示游标引用的基本表。
  • Sp_describe_cursor_columns:用于显示游标结果集中列的属性。

下面介绍一下如何使用Sp_cursor_list过程显示当前作用域内的游标及其属性。
Sp_cursor_list过程的语法结构如下所示:

sp_cursor_list @cursor_return=cursor_variable_name OUTPUT,
@cursor_scope=cursor_scope

上述代码中的cursor_variable_name表示的是为游标创建的变量,该变量中存储了作用域内的游标及其属性。cursor_scope表示的是游标的作用域,其取值如下所示:

  • 如果返回所有的LOCAL游标,则cursor_scope取值为1。
  • 如果返回所有的GLOBAL游标,则cursor_scope取值为2。
  • 如果返回所有的LOCAL和GLOBAL游标,则cursor_scope取值为3。

下面通过一个示例来说明如何使用Sp_cursor_list过程来显示系统中所有的GLOBAL游标。
【上机实战】
使用Sp_cursor_list过程来显示数据库MyDatas中所有的GLOBAL游标及其属性,其实现的代码如下所示。

DECLARE @reportout CURSOR
EXEC sp_cursor_list @cursor_return=@reportout OUTPUT,
@cursor_scope=2
FETCH NEXT FROM @reportout
WHILE(@@FETCH_STATUS=0)
BEGIN
  FETCH NEXT FROM @reportout
END 
DEALLOCATE @reportout

代码执行以后,其执行结果如图14.8所示。
在这里插入图片描述
图14.8 数据库MyDatas中所有的GLOBAL游标及其属性

14.4 Oracle中游标的应用
Oracle中的游标在定义和使用上与标准SQL中游标的使用有很大的区别。在Oracle中,游标被定义为一个指向上下文的句柄或指针。本节中将讲解如何在Oracle中使用游标。
14.4.1 显示游标
在PL/SQL程序中使用的游标称为显式游标,其使用方法也包括创建游标、打开游标、提取数据和关闭游标4个步骤。
1.创建游标
创建游标使用DECLEAR语句来实现,其语法格式如下所示。

CURSOR 游标名[(参数1 数据类型[参数2 数据类型...])]

IS SELECT语句;
上述语句中的参数是可选部分,所定义的参数可以出现在SELECT语句的WHERE子句中。如果定义了参数,则必须在打开游标时传递相应的实际参数。SELECT语句是对表或视图的查询语句,甚至也可以是联合查询。可以带WHERE条件、ORDER BY或GROUP BY等子句,但不能使用INTO子句。在SELECT语句中可以使用在定义游标之前定义的变量。
在游标定义中SELECT语句中不一定非要表可以是视图,也可以从多个表或视图中选择。
2.打开游标
使用游标中的值之前应该首先打开游标,打开游标初始化查询处理。打开游标的语法格式如下所示。

OPEN 游标名[(实际参数1[实际参数2,...])];

打开游标时,SELECT语句的查询结果就被传送到了游标工作区。
3.提取数据
从游标得到一行数据使用FETCH命令。每一次提取数据后,游标都指向结果集的下一条数据,提前数据的语句格式如下所示。

FETCH cursor_name INTO variable[,variable,...]

对于SELECT定义的游标的每一列,FETCH变量列表都应该有一个变量与之相对应。
游标打开后有一个指针指向数据区,FETCH语句一次返回指针所指的一行数据,要返回多行需重复执行,可以使用循环语句来实现。控制循环可以通过判断游标的属性来进行。
4.关闭游标
显式游标打开后,必须显式地关闭。游标一旦关闭,游标占用的资源就被释放,游标变成无效,必须重新打开才能使用,关闭游标的语句格式如下所示。

CLOSE 游标名; 

【上机实战】
创建游标cursor_goods,在货物信息表(t_goods)中检索货物编号为“1003”的数据信息,其实现的代码如下所示。

DECLARE CURSOR cursor_good
IS SELECT g_id,g_title,g_nums,g_value,g_place
FROM t_goods
WHERE g_id='1003';
g_id varchar(10);
g_title varchar(20);
g_nums int;
g_value float;
g_place varchar(30);
BEGIN
  OPEN cursor_good;
  FETCH cursor_good INTO g_id,g_title,g_nums,g_value,g_place;
  DBMS_OUTPUT.PUT_LINE('编号:'|| g_id || '名称:'|| g_title
  || '数量:'|| to_char(g_nums) || '单价:' || to_char(g_value) || '地点:' || g_place);
  CLOSE cursor_good;
END;

代码执行以后,其执行结果如图14.9所示。
在这里插入图片描述
图14.9 显示游标的应用
说明:在Oracle中创建、打开、检索与关闭显式游标的语法和用法与标准SQL中的语法和用法相同。有关这方面的内容请参照标准SQL中游标的相关语法和用法。

14.4.2 隐式游标
与显式游标不同,隐式游标并不被应用程序打开或者关闭。隐式游标主要用在UPDATE、DELETE等语句之后,用于查看刚刚执行的操作是否执行成功。
当系统使用一个隐式游标时,可以通过隐式游标的属性来了解操作的状态和结果,进而控制程序的流程。隐式游标可以使用名字SQL来访问,但要注意,通过SQL游标名总是只能访问前一个处理操作或单行SELECT操作的游标属性。所以通常在刚刚执行完操作之后,立即使用SQL游标名来访问属性。游标的属性有四种,分别是SQL %ISOPEN,SQL %FOUND,SQL %NOTFOUND,SQL %ROWCOUNT。
(1)SQL%ISOPEN返回的类型为布尔型,判断游标是否被打开,如果打开%ISOPEN等于true,否则等于false,即执行过程中为真,结束后为假。
(2)SQL%NOTFOUND返回值为布尔型,判断游标所在的行是否有效,如果有效,则%FOUNDD等于true,否则等于false,即与%FOUND属性返回值相反。
(3)SQL%FOUND返回值的类型为布尔型,值为TRUE代表插入 删除 更新或单行查询操作成功。
(4)SQL%ROWCOUNT返回值类型为整型,返回当前位置为止游标读取的记录行数,即成功执行的数据行数。
【上机实战】
将货物信息表(t_goods)中货物编号为“1009”的货物单价更改为3.0,数量改为5。如果该数据信息不存在,则向货物信息表(t_goods)中添加该信息。为了便于读者进行分析比较,现将使用隐式游标之前货物信息表(t_goods)中的数据信息显示出来。

select * from t_goods

代码执行以后,其执行结果如图14.10所示。
在这里插入图片描述
图14.10 使用隐式游标之前货物信息表(t_goods)中的数据信息
在Oracle中使用隐式游标的实现代码如下所示。

BEGIN
  UPDATE t_goods 
  SET g_nums=5,g_value=3.0
  WHERE g_id='1009';
  /* 使用隐式游标 */
  IF SQL%ROWCOUNT=0 THEN  
  INSERT INTO t_goods(g_id,g_title,g_nums,g_value,g_place)
  VALUES('1009','日常用品',5,3.0,'吉林省长春市');
  END IF;
END;

代码执行以后,查询货物信息表(t_goods)中的数据信息如图14.11所示。
在这里插入图片描述
图14.11使用隐式游标之前货物信息表(t_goods)中的数据信息
从上述的输出结果可以看出,由于编号为“1009”的数据记录不存在,因此将该数据记录插入到了货物信息表(t_goods)当中。
14.4.3 参数化游标
与存储过程和函数一样,也可以给游标传递参数,本节中将讲解一下给游标传递参数的实现方法。
【语法说明】
在游标中使用参数的语法结构如下所示。

DECLARE CURSOR cursor_name[(parameter[,parameter],...)]
IS select_statment;

其中参数定义的语句如下。
parameter_name [IN] data_type[{:=|DEFAULT} value]
上述代码中的cursor_name表示游标的名称,parameter表示游标参数的名称,select_statment表示SQL语句的表达式,parameter_name表示定义参数的名称,data_type表示的是数据类型。

说明:游标参数只能接收传递的值,而不能返回值。在定义游标参数时,只能定义参数的数据类型,而不能定义其参数的大小。

【上机实战】
创建带有参数的游标cursor_place,从货物信息表(t_goods)中检索指定地点的货物信息,将其结果从游标中检索并显示出来,其实现的代码如下所示。

DECLARE
CURSOR cursor_place(Place varchar2)
IS
SELECT * FROM t_goods
WHERE g_place=Place;
cinfo cursor_place %ROWTYPE;
BEGIN
 /* 打开游标,同时赋予参数值 */
 OPEN cursor_place('吉林省长春市');
 LOOP
 FETCH cursor_place INTO cinfo;
 EXIT WHEN cursor_place %NOTFOUND;
 DBMS_OUTPUT.PUT_LINE('编号:'|| cinfo.g_id || ' 名称:'|| cinfo.g_title || ' 数量:'|| to_char(cinfo.g_nums) || ' 单价:' || to_char(cinfo.g_value) || ' 地点:' || cinfo.g_place);
 END LOOP;
 CLOSE cursor_place;
END;

代码执行以后,其执行结果如图14.12所示。
在这里插入图片描述
图14.12 参数化游标应用示例
14.4.4 在游标中使用循环语句
在游标中通常使用循环的方法逐条提取所需要的数据信息。在Oracle中主要通过LOOP循环、WHILE循环和FOR循环3种方法从游标中逐条提取数据。下面分别介绍这3种不同的循环方法。
1.LOOP循环
在使用LOOP循环时要通过AND LOOP语句来结束循环。并且要在循环体中添加跳出循环的语句。即EXIT WHEN语句。否则就会出现无限循环的现象。
【上机实战】
创建带有参数的游标cursor_loop,从货物信息表(t_goods)中检索指定编号范围内的货物信息,将其结果从游标中检索并显示出来,其实现的代码如下所示。

DECLARE
CURSOR cursor_loop(g_id1 int,g_id2 int)
IS
SELECT * FROM t_goods
WHERE g_id>=g_id1 and g_id <= g_id2;
cinfo cursor_loop %ROWTYPE;
BEGIN
 /* 打开游标,同时赋予参数值 */
 OPEN cursor_loop(1002,1007);
 LOOP
 FETCH cursor_loop INTO cinfo;
 EXIT WHEN cursor_loop %NOTFOUND;
 DBMS_OUTPUT.PUT_LINE('编号:'|| cinfo.g_id || ' 名称:'|| cinfo.g_title || ' 数量:'|| to_char(cinfo.g_nums) || ' 单价:' || to_char(cinfo.g_value) || ' 地点:' || cinfo.g_place);
 END LOOP;
 CLOSE cursor_loop;
END;

代码执行以后,其执行结果如图14.13所示。
在这里插入图片描述
图14.13 在游标中应用LOOP循环语句的应用示例
2.WHILE循环
WHILE循环是先判断条件后执行循环,即只有满足条件之后,才能够执行其循环体内的内容,这一点与LOOP循环有所不同。
【上机实战】
创建带有参数的游标cursor_while,从货物信息表(t_goods)中检索指定编号范围内的货物信息,将其结果从游标中检索并显示出来,其实现的代码如下所示。

DECLARE
CURSOR cursor_loop(g_id1 int,g_id2 int)
IS
SELECT * FROM t_goods
WHERE g_id>=g_id1 and g_id <= g_id2;
cinfo cursor_loop %ROWTYPE;
BEGIN
 /* 打开游标,同时赋予参数值 */
 OPEN cursor_loop(1001,1006);
FETCH cursor_loop INTO cinfo;
 WHILE cursor_loop %FOUND
 LOOP
 DBMS_OUTPUT.PUT_LINE('编号:'|| cinfo.g_id || ' 名称:'|| cinfo.g_title || ' 数量:'|| to_char(cinfo.g_nums) || ' 单价:' || to_char(cinfo.g_value) || ' 地点:' || cinfo.g_place);
 FETCH cursor_loop INTO cinfo;
 END LOOP;
 CLOSE cursor_loop;
END;

代码执行以后,其执行结果如图14.14所示。
在这里插入图片描述
图14.14 在游标中应用WHILE循环语句的应用示例
3.FOR循环
FOR循环是显示游标的一种快捷使用方式,通过FOR循环,可以依次读取结果集中的行数据。用于FOR循环的游标不需要显式地打开游标、关闭游标、读取游标数据和定义存放数据的变量等。
说明:当FOR循环开始执行时,游标被自动打开,每循环一次,系统就会自动读取当前行的数据信息,当退出FOR循环时,游标被自动关闭。
【上机实战】
创建带有参数的游标cursor_for,从货物信息表(t_goods)中检索指定编号范围内的货物信息,将其结果从游标中检索并显示出来,其实现的代码如下所示。

DECLARE
CURSOR cursor_for(g_id1 int,g_id2 int)
IS
SELECT * FROM t_goods
WHERE g_id>=g_id1 and g_id <= g_id2;
cinfo cursor_for %ROWTYPE;
BEGIN
 FOR cinfo IN cursor_for(1002,1008)
 LOOP
 DBMS_OUTPUT.PUT_LINE('编号:'|| cinfo.g_id || ' 名称:'|| cinfo.g_title || ' 数量:'|| to_char(cinfo.g_nums) || ' 单价:' || to_char(cinfo.g_value) || ' 地点:' || cinfo.g_place);
 END LOOP;
END;

代码执行以后,其执行结果如图14.15所示。
在这里插入图片描述
图14.15 在游标中应用FOR循环语句的应用示例

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HeartBest丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值