13 游标

1.背景

       游标,是指一种能从包括多条数据记录的结果集中每次提取一条记录的机制。简单地说,游标提供了一种在服务器内部处理结果集的方法,它可以识别一个数据集合内部指定的工作行,从而可以有选择地按行采取操作。游标是映射在结果集中一行数据上的位置实体,有了游标,用户就可以访问结果集中的任意一行数据了,将游标放置到某行后,即可对该行数据进行操作,如提取当前行的数据等。

2.应用场景及语句

1.声明,打开,关闭以及使用游标(CURSOR,FETCH ...INTO...,OPEN,CLOSE,LOOP...EXIT WHEN 游标名%NOTFOUND...END LOOP

--声明游标(会输出按学号排列的前三行学号,姓名)
DECLARE
C_NO STU.NO%TYPE;
C_NAME STU.NAME%TYPE;
CURSOR CUR_STU IS
SELECT NO,NAME FROM STU ORDER BY NO;
BEGIN
--打开游标(OPEN)
OPEN CUR_STU;
FETCH CUR_STU INTO C_NO,C_NAME;
DBMS_OUTPUT.PUT_LINE('xuehao:'||C_NO||'name:'||C_NAME);
FETCH CUR_STU INTO C_NO,C_NAME;
DBMS_OUTPUT.PUT_LINE('xuehao:'||C_NO||'name:'||C_NAME);
FETCH CUR_STU INTO C_NO,C_NAME;
DBMS_OUTPUT.PUT_LINE('xuehao:'||C_NO||'name:'||C_NAME);
--关闭游标(CLOSE)
CLOSE CUR_STU;
DBMS_OUTPUT.PUT_LINE('游标已关闭');
END;
--循环语句中使用游标(循环输出所有学号,姓名信息)
DECLARE
C_NO STU.NO%TYPE;
C_NAME STU.NAME%TYPE;
CURSOR CUR_STU IS
SELECT NO,NAME FROM STU ORDER BY NO;
BEGIN
OPEN CUR_STU;
LOOP
FETCH CUR_STU INTO C_NO,C_NAME;
EXIT WHEN CUR_STU%NOTFOUND;--循环结束条件
DBMS_OUTPUT.PUT_LINE('xuehao:'||C_NO||'name:'||C_NAME);
END LOOP;
CLOSE CUR_STU;
END;

*在数据库中,游标主要功能是用于提取表中以行为单位的数据记录

*对视图的也可进行游标操作,与表同样。注意,当视图数据发生变化时,已打开游标的数据不会随着改变。因为其是静态的,只有用户重新打开游标后数据才会更新。

*提取整行数据,可使用数据定义‘STU_ROW STU表%ROWTYPE’或者‘STU_ROW 游标名%ROWTYPE’,直接FETCH...INTO。

2.声明带参数的游标

--带参数的游标
DECLARE
CURSOR CUR_STU(DEPT VARCHAR2)
--带默认值参数的游标
--CURSOR CUR_STU(DEPT VARCHAR2:='计算机')
IS 
SELECT * FROM STU WHERE SDEPT=DEPT;
STU_ROW CUR_STU%ROWTYPE;
BEGIN
OPEN CUR_STU('ENGLISH');
LOOP ... END LOOP;
CLOSE CUR_STU;
END;

*注意在声明参数时,参数只定义类型,没有大小

3.使用游标FOR循环(精简代码,建议多使用游标FOR循环)

--游标FOR循环(不需要显式打开,关闭提取数据及定义存放数据的变量)
DECLARE
CURSOR CUR_STU IS
SELECT SNO,SNAME,SDEPT FROM STU;
STU_ROW STU%ROWTYPE;
BEGIN
FOR STU_ROW IN CUR_STU
LOOP
...
END LOOP;
END; 
游标FOR循环中使用子查询(无需声明游标)(可对比上语句)
DECLARE
STU_ROW STU%ROWTYPE;
BEGIN
FOR STU_ROW IN (SELECT * FROM STU)
LOOP
...
END LOOP;
END; 

4.使用游标的其它操作(使用WHERE CURRENT OF 游标名)。游标更新数据,游标删除数据,判断游标是否被打开,获取游标的记录行数。

--使用游标更新数据(WHERE CURRENT OF CUR_STU)
DECLARE
CURSOR CUR_STUIS
SELECT * FROM STU FOR UPDATE;
STU_ROW STU%ROWTYPE;
BEGIN
OPEN CUR_STU;
LOOP
FETCH CUR_STU INTO STU_ROW;
EXIT WHEN CUR_STU%NOTFOUND;
UPDATE STU SET SAGE=SAGE+1 WHERE CURRENT OF CUR_STU;
END LOOP;
CLOSE CUR_STU;
END;
--删除数据(删除学号为123的学生信息)
DECLARE
CURSOR CUR_STU IS
SELECT * FROM STU FOR UPDATE;
STU_ROW STU%ROWTYPE;
BEGIN
OPEN CUR_STU;
LOOP
FETCH CUR_STU INTO STU_ROW;
EXIT WHEN CUR_STU%NOTFOUND;
IF STU_ROW.SNO='123' THEN DELETE FROM STU WHERE CURRENT OF CUR_STU;
END IF;
END LOOP;
CLOSE CUR_STU;
END;
--判断游标是否被打开
DECLARE
CURSOR CUR_STU IS
SELECT * FROM STU;
BEGIN
OPEN CUR_STU;
IF CUR_STU%ISOPEN=FALSE THEN DBMS_OUTPUT.PUT_LINE('游标未打开!');
ELSE DBMS_OUTPUT.PUT_LINE('游标已打开!');
END IF;
CLOSE CUR_STU;
END;
--获取游标读取的记录行数
DECLARE
CURSOR CUR_STU IS SELECT * FROM STU WHERE SDEPT='COMPUTER';
SUM INTEGER;STU_ROW STU%ROWTYPE;
BEGIN OPEN CUR_STU;
LOOP ... END LOOP;
SUM:=CUR_STU%ROWCOUNT;
DBMS_OUTPUT.PUT_LINE('行数:'||SUM);
CLOSE CUR_STU;
END;

*ISOPEN是游标重要属性之一,用于判断游标是否被打开。还有:%FOUND,%NOTFOUND,%ISOPEN,%ROWCOUNT.

### 数据游标的概述 数据游标是一种能够从包括多条数据记录的结果集中每次提取一条记录的机制[^2]。它充当指针的角色,尽管可以遍历结果集中的所有行,但一次仅指向一行。这使得游标成为处理大量数据的理想工具,尤其是在内存不足以容纳整个结果集的情况下[^3]。 ### 创建和使用游标的步骤 为了更好地理解如何创建并利用游标,下面提供了一个简单的例子,该实例展示了如何声明打开、获取以及关闭一个游标: #### 声明游标 首先定义游标名称及其关联的选择语句: ```sql DECLARE product_cursor CURSOR FOR SELECT ProductID, Name FROM Production.Product; ``` #### 打开游标 通过执行`OPEN`命令启动游标: ```sql OPEN product_cursor; ``` #### 获取当前行的数据 使用`FETCH NEXT INTO`指令读取下一行并将字段值赋给局部变量: ```sql DECLARE @ProductID INT, @ProductName NVARCHAR(50); FETCH NEXT FROM product_cursor INTO @ProductID, @ProductName; WHILE @@FETCH_STATUS = 0 BEGIN -- 对每一行进行操作... FETCH NEXT FROM product_cursor INTO @ProductID, @ProductName; END; ``` #### 关闭与释放资源 完成迭代后应始终记得先关闭再解除分配游标以回收系统资源: ```sql CLOSE product_cursor; DEALLOCATE product_cursor; ``` 上述代码片段演示了基本的操作流程,实际应用中可能还需要考虑异常情况下的错误处理逻辑。 ### 游标的适用场景 当面对较大的结果集时,由于这些集合无法一次性加载到客户端应用程序的工作区里,因此非常适合采用游标分批取出所需的信息来进行逐一处理。此外,在某些编程环境中可以直接将表格内容作为结构化类型的变量来访问特定列的内容,例如GBase 8s支持`.元素名`的方式引用单个属性值[^4]。 ### 性能考量 值得注意的是,虽然游标提供了灵活性,但在性能方面可能存在劣势,因为它们通常涉及更多的网络往返次数,并可能导致锁定时间延长等问题。所以在决定是否使用游标之前应当权衡利弊,评估是否有更高效的替代方案可用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值