Oracle(七)游标

基本概念

游标是SQL的一个内存工作区,由系统或用户以变量的形式定义

游标的作用就是用于临时存储从数据库中提取的数据块。在某些情况下,需要把数据从存放在磁盘的表中调到计算机内存中进行处理,最后将处理结果显示出来或最终写回数据库。这样数据处理的速度才会提高,否则频繁的磁盘数据交换会降低效率。

游标有两种类型:显式游标和隐式游标

对于SELECT…INTO…查询语句,一次只能从数据库中提取一行数据,对于这种形式的查询和DML操作,系统都会使用一个隐式游标

如果要提取多行数据,就要定义一个显式游标,并通过与游标有关的语句进行处理。显式游标对应一个返回结果为多行多列的SELECT语句。

游标一旦打开,数据就从数据库中传送到游标变量中,然后应用程序再从游标变量中分解出需要的数据,并进行处理。

关系数据库管理系统实质是面向集合的,因此我们必须借助于游标来进行面向单条记录的数据处理

隐式游标

执行一个SQL语句时,ORACLE会自动创建一个隐式游标, 这个游标是内存中处理该语句的工作区域,隐式游标主要处理UPDATE 、DELETE的执行结果,特殊情况下也处理SELECT的查询结果,隐式游标也有属性,当使用隐式游标的属性时,需要加上它的默认名称——SQL。隐式游标的属性值只反映最近的一条SQL语句的处理结果

使用显式游标的4个步骤:

  • 说明游标。
  • 打开游标。
  • 读取数据。
  • 关闭游标。

游标控制语句

声明游标语句CURSOR

DECLARE CURSOR 游标名
[ (参数列表) ]
IS
SELECT语句;

示例:

DECLARE CURSOR MyCur(varType NUMBER) IS
  SELECT UserId, UserName FROM Users
  WHERE UserType = varType;

打开游标语句OPEN

打开游标时,数据库数据将被存储到游标变量中。

OPEN 游标名 [ (参数列表) ];

注:显式游标必须事先声明,才能使用OPEN语句打开,否则会出现错误

游标取值语句FETCH

游标取值时不需要为游标名加上参数,因为其中存储的数据已经在游标打开时存储进去,其中的数据已经相对固定。其取值对应的变量应与定义游标时select获取的列对应。

FETCH 游标名 INTO 变量列表;

示例:

FETCH MyCur INTO varId, varName;

关闭游标语句CLOSE

CLOSE 游标名;

显式游标使用完后,应该及时关闭,从而释放存储空间。

完整应用示例:

SET ServerOutput ON;   
DECLARE  --开始声明部分
  varId  NUMBER;  --声明变量,用来保存游标中的用户编号
  varName VARCHAR2(50);   --声明变量,用来保存游标中的用户名
  --定义游标
  CURSOR MyCur(varType NUMBER) IS
    SELECT UserId, UserName FROM Users    WHERE UserType = varType;
BEGIN   --开始程序体
  OPEN MyCur(1); --打开游标,参数为1,表示读取用户类型编号为1的记录
  FETCH MyCur INTO varId, varName;  --读取当前游标位置的数据
  CLOSE MyCur;   --关闭游标
  dbms_output.put_line('用户编号:' || varId ||', 用户名:' || varName); --显示数据
END;   --结束程序体

游标属性

  • %ISOPEN属性
    此属性多用于在程序体中判断游标是否被打开:
IF MyCur%ISOPEN = FALSE Then
    OPEN MyCur(2);
  END IF;
  • %FOUND属性和%NOTFOUND属性
    使用%FOUND属性可以循环执行游标读取数据
  WHILE MyCur%FOUND --如果当前游标有效,则执行循环
  LOOP
    dbms_output.put_line('用户编号:' || varId ||', 用户名:' || varName); --显示读取的数据
    FETCH MyCur INTO varId, varName;  --读取当前游标位置的数据
  END LOOP;
  • %ROWCOUNT属性
    用于标记当前游标所在位置
FETCH MyCur INTO varId, varName;  --读取当前游标位置的数据
  WHILE MyCur%FOUND --如果当前游标有效,则执行循环
  LOOP
    dbms_output.put_line('用户编号:' || varId ||', 用户名:' || varName
    IF MyCur%ROWCOUNT = 2 THEN
      EXIT;
    END IF;
    FETCH MyCur INTO varId, varName;  --读取当前游标位置的数据
  END LOOP;

游标FOR循环

记录:
其用处在于将多个变量放置在一个群体中,类似于C++的struct结构

TYPE 记录类型名 IS RECORD
   ( 字段声明 [, 字段声明] …);
  

TYPE User_Record_Type IS RECORD
  ( UserId             Users.UserId%Type, 
   UserName        Users.UserName%Type);

定义记录变量的方法与定义普通变量的方法相同,语法如下

记录变量名 记录变量类型

var_UserRecord User_Record_Type;

访问记录中的字段

记录名.字段名

var_UserRecord.UserId

如果要声明的记录类型与某个表或视图的结构完全相同,则可以直接使用%ROWTYPE属性来定义记录变量:

变量名  表名%ROWTYPE;

var_UserRecord1 User%ROWTYPE;

使用这种方法定义记录变量,不需要声明记录类型。记录变量的字段名与对应表或视图中的列名一致,而且拥有相同的数据类型。

游标FOR循环的语法:
由以下可知,for循环一定有记录

FOR <记录名> IN <游标名> LOOP
  语句1;
  语句2;
  …
  语句n;
END LOOP;

带子查询的游标FOR循环的语法
就是将select替代游标的作用

FOR <记录名> IN <SELECT子查询> LOOP
  语句1;
  语句2;
  …
  语句n;
END LOOP;

管理游标结果集

修改游标结果集中的行

定义游标时可以使用FOR UPDATE子句指定可以更新的列:

DECLARE CURSOR 游标名
[ (参数列表) ]
IS
SELECT语句
FOR UPDATE OF 可以更新的列名;


DECLARE CURSOR MyEmpCursor (varDepId NUMBER) IS
  SELECT Last_name, Salary FROM HR.Employees
  WHERE Department_id = varDepId
  FOR UPDATE OF salary;

使用UPDATE语句修改游标中数据:
需要使用WHERE CURRENT OF子句指定要更新的游标:

UPDATE 表名 SET子句
WHERE CURRENT OF 游标名

DECLARE CURSOR MyEmpCursor(varDepId NUMBER) IS
  SELECT Last_name, Salary FROM HR.Employees
  WHERE Department_id = varDepId
  FOR UPDATE OF Salary;
BEGIN
  FOR rec1 IN MyEmpCursor(1) LOOP
    UPDATE HR.Employees SET Salary = Salary + 100 
    WHERE CURRENT OF MyEmpCursor;
  END LOOP;
END;

删除游标结果集中的行

DELETE FROM 表名
WHERE CURRENT OF 游标名

DECLARE CURSOR MyEmpCursor (varDepId NUMBER) IS
  SELECT Last_name, Salary FROM HR.Employees
  WHERE Department_id = varDepId
  FOR UPDATE OF salary;
BEGIN
  FOR rec1 IN MyEmpCursor(1) LOOP
    DELETE FROM HR.Employees 
    WHERE CURRENT OF MyEmpCursor;
  END LOOP;
END;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值