Oracle数据库中的游标知识点及实例(六)
作者:快盘下载 人气:目录
1.游标
2.游标的声明
;1;显式游标声明
①定义游标之后打开游标
②FETCH读取数据
;2;隐式游标声明
3.游标FOR循环
学习Oracle数据库相关基本操作;一;
学习Oracle数据库的新建表的基本操作;二;
学习Oracle数据库新建数据库操作;三;
学习Oracle数据库并对数据进行查询;插入等操作;四;
关于Oracle中的关闭和启动数据库的几种方式;五;
Oracle中含替换变量的查询;二;
Oracle中数据库的查询;三;
PL/SQL基础知识点;一;
PL/SQL变量;常量和数据类型;二;
PL/SQL基本程序结构和语句;三;
Oracle中系统内置函数;四;
Oracle中用户自定义函数;五;
1.游标
为什么需要游标呢?
我们之前使用SQL的语句通常查询数据库中的数据的时候会产生一组的结果集;然而这种结果是不能看成是一个单元来处理的;所以应用需要一种机制来保证每次处理结果集中的一行或者几行;那么游标就提供了这样的机制;可以对结果集进行逐行的处理;与某个查询结果相联系;可以指向结果集的任意位置;方便对指定位置的数据进行操作;。
游标包含;显式游标和隐式游标。
为什么需要游标呢?
我们之前使用SQL的语句通常查询数据库中的数据的时候会产生一组的结果集;然而这种结果是不能看成是一个单元来处理的;所以应用需要一种机制来保证每次处理结果集中的一行或者几行;那么游标就提供了这样的机制;可以对结果集进行逐行的处理;与某个查询结果相联系;可以指向结果集的任意位置;方便对指定位置的数据进行操作;。
游标包含;显式游标和隐式游标。
2.游标的声明
;1;显式游标声明
DECLARE CURSOR <游标名>
IS
<SELECT 语句>
使用游标之前首先需要打开游标;
OPEN <游标名>
①定义游标之后打开游标
当打开游标之后;可以使用系统变量%ROWCOUNT返回最后一次提取到数据行的序列号。打开游标之后;且提取数据之前可访问%ROWCOUNT值;返回值为0;第一次访问;那么提取到的数据行为0;。
DECLARE CURSOR XSB_CUR
IS
SELECT SID,SNAME
FROM XSB;
BEGIN
OPEN XSB_CUR;
DBMS_OUTPUT.PUT_LINE(XSB%ROWCOUNT);
END;
DECLARE CURSOR <游标名>
IS
<SELECT 语句>
使用游标之前首先需要打开游标;
OPEN <游标名>
①定义游标之后打开游标
当打开游标之后;可以使用系统变量%ROWCOUNT返回最后一次提取到数据行的序列号。打开游标之后;且提取数据之前可访问%ROWCOUNT值;返回值为0;第一次访问;那么提取到的数据行为0;。
DECLARE CURSOR XSB_CUR
IS
SELECT SID,SNAME
FROM XSB;
BEGIN
OPEN XSB_CUR;
DBMS_OUTPUT.PUT_LINE(XSB%ROWCOUNT);
END;
②FETCH读取数据
FETCH <游标名> [ INTO <变量名>,...n]
提示;这里的INTO主要将从当前游标所指向的位置读取的数据赋值给后面的变量;和前面所讲的 SELECT SID INTO <变量名>差不多;。
关于FETCH读取数据;FETCH每一次读取一行的数据;然后自动将游标指针移动指向下一个数据行;当检索到最后一行数据时;再一次执行FETCH读取数据的话;那么会操作失败;并将游标%NOTFOUND设置为TRUE;
例子1;从学生表XSB中使用游标读取学生的学号;姓名和学分
SET SERVEROUTPUT ON; DECLARE --声明变量 ID XSB.sid%TYPE; NAME XSB.sname%TYPE; grade XSB.score%TYPE; --声明游标 CURSOR XSB_CUR IS SELECT sid,sname,score FROM XSB; BEGIN --首先打开游标 OPEN XSB_CUR; --读取数据 FETCH XSB_CUR INTO ID,NAME,grade; WHILE XSB_CUR%FOUND LOOP DBMS_OUTPUT.PUT_LINE(;学号: ;||to_char(ID)||; 姓名: ;||to_char(NAME)||; 学分: ;||to_char(grade)); --读取数据 FETCH XSB_CUR INTO ID,NAME,grade; END LOOP; --关闭游标 CLOSE XSB_CUR; END;
注;如果试图打开一个已经打开的游标或者关闭一个已经关闭了的游标;都会出错。因此可以采用下面的语句首先进行判断游标的状态;
IF mycur%ISOPEN THEN
FETCH mycur INTO [<变量名>,...n];
ELSE
OPEN mycur;
END
;2;隐式游标声明
如果在PL/SQL程序段中使用DML;DELETE,UPDATE,INSERT;或者SELECT语句进行操作的话;PL/SQL会隐含地处理游标定义。
如果在PL/SQL程序段中使用DML;DELETE,UPDATE,INSERT;或者SELECT语句进行操作的话;PL/SQL会隐含地处理游标定义。
例子;使用隐式游标的方式查询学号为‘151101’学生的信息;
SET SERVEROUTPUT ON;
DECLARE
ID XSB.sid%TYPE;
NAME XSB.sname%TYPE;
GRADE XSB.score%TYPE;
BEGIN
SELECT sid,sname,score into ID,NAME,GRADE
FROM XSB
where sid=;151101;;
--这里使用隐式游标判断是否查询成功
IF SQL%FOUND THEN
DBMS_OUTPUT.PUT_LINE(;查询成功: ;||; 学号: ;||to_char(ID)||; 姓名: ;||to_char(NAME)||; 学分: ;||to_char(GRADE));
END IF;
END;
隐式游标注意的点;
;1;每一个隐式游标必须有一个INTO;当使用SELECT语句的时候;;
;2;与显式游标一样;接收数据目标变量的数目;数据类型要SELECT查询的数据类型相同;
;3;隐式游标一次仅返回一行的数据;使用的使用必须检查异常;关于异常前面已经讲述;;
;4;为确保隐式游标仅返回一行数据;可以使用ROWNUM=1来限定;表示返回一行数据。
3.游标FOR循环
其实前面在讲述显式游标的时候;举的那个例子是使用WHILE-LOOP-END循环来使用;也可以转换为FOR循环。
FOR<记录变量名> IN <游标名> [(<参数1>,[,<参数2>]...)] LOOP
语句段
END LOOP;
例子1;从学生表XSB中使用游标读取学生的学号;姓名和学分。
SET SERVEROUTPUT ON;
DECLARE
--声明变量
ID XSB.sid%TYPE;
NAME XSB.sname%TYPE;
grade XSB.score%TYPE;
--声明游标
CURSOR XSB_CUR
IS
SELECT sid,sname,score
FROM XSB;
BEGIN
FOR curValue IN XSB_CUR LOOP
ID:=curValue.sid;
NAME:=curValue.sname;
grade:=curValue.score;
DBMS_OUTPUT.PUT_LINE(;学号: ;||to_char(ID)||; 姓名: ;||to_char(NAME)||; 学分: ;||to_char(grade));
END LOOP;
END;
例子2;用PL/SQL定义游标;从雇员表中显示工资大于1000的记录;只要姓名、部门编号和工资并且删除编号为奇数的员工;
--select emp.ename,emp.deptno,emp.sal
-- from emp
-- where sal>1000 and ROWNUM=1;
SET SERVEROUTPUT ON;
--声明变量
DECLARE
v_sal number;
v_ename char(20);
v_dept int;
k int;
--定义游标
cursor csalary
IS
select ename,deptno,sal
from emp
where sal>1000;
BEGIN
--使用for循环游标
FOR valText IN csalary loop
v_ename:=valText.ename;
v_dept:=valText.deptno;
v_sal:=valText.sal;
k:=csalary%rowcount;
--对于奇数的打印和输出
if mod(k,2)=1 and csalary%found then
DBMS_OUTPUT.PUT_LINE(;v_name: ;||to_char(v_ename)||; v_dept: ;||
to_char(v_dept)||;v_sal: ;||to_char(v_sal));
end if;
end loop;
end;
例子3;游标的应用;编写PL/SQL块;将员工表EMP中的部门编号为10的所有员工删除;统计删除的人数及删除人的平均工资。
SET SERVEROUTPUT ON;
DECLARE
v_salNUM number:=0;
BEGIN
select avg(sal) into v_salNUM
from emp
where deptno=10;
delete
from emp
where deptno=10;
if sql%found then
DBMS_OUTPUT.PUT_LINE(;删除的人数: ;||to_char(sql%rowcount));
DBMS_OUTPUT.PUT_LINE(;删除人的平均工资数: ;||to_char(v_salNUM));
end if;
end;
rollback;
提示;可以看到当使用FOR循环的时候就不需要使用OPEN和CLOSE语句;并且程序的结构上看起来更加的清晰和容易理解。
加载全部内容