游标的概念
游标是数据库中可以操作的一块内存区,可以方便的帮我们从数据库中获取数据。一般使用游标用来遍历数据。
使用游标的语法:
declare
--声明游标变量
cursor 游标变量名称 is sql语句;
begin
-- 打开游标
open 游标变量名称;
loop
--从游标中获取数据
fetch 游标变量名称 into rowtype类型变量/record类型变量;
---判断是否从游标中获取到了数据,如果没有获取到数据 ,应该跳出循环
if 游标变量%notfound then
exit;
end if;
语句块;
end loop;
--关闭游标
close 游标变量名称;
end;
举例:输出部门表的所有内容。
--输出部门表的所有数据 declare --声明游标变量 cursor cur_dept is select * from dept; --声明行类型变量,用来接收游标获取到的数据 v_dept dept%rowtype; begin --打开游标 open cur_dept; loop --从游标中获取数据 fetch cur_dept into v_dept; -- 判断是否从游标中获取到了数据,如果没有获取数据跳出循环 --if cur_dept%notfound then -- exit; --end if; --if 可以简写成如下形成 exit when cur_dept%notfound; --打印数据 dbms_output.put_line('第'||cur_dept%rowcount||'行,部门编号:'||v_dept.deptno||',部门名称:'||v_dept.dname); end loop; --关闭游标 close cur_dept; end;
可以使用游标名称%属性名称 来访问游标的属性,游标常用的有四个属性:
游标分显示游标和隐含游标两种类型
显式游标
参数游标
使用游标的时候可以给游标定义参数,这样游标就可以传不同的参数多次使用了
举例:写一个游标,根据部门编号,打印该部门下员工的信息
declare --声明游标变量 ,加入参数 cursor cur_emp(v_deptno number) is select * from emp where deptno=v_deptno; v_emp emp%rowtype; begin --打印部门编号为10的员工的信息 --打开游标 open cur_emp(10); loop fetch cur_emp into v_emp; exit when cur_emp%notfound; dbms_output.put_line('员工编号:'||v_emp.empno||',员工姓名:'||v_emp.ename); end loop; --关闭游标 close cur_emp; dbms_output.put_line('======'); --打印部门编号为20的员工的信息 --打开游标 open cur_emp(20); loop fetch cur_emp into v_emp; exit when cur_emp%notfound; dbms_output.put_line('员工编号:'||v_emp.empno||',员工姓名:'||v_emp.ename); end loop; --关闭游标 close cur_emp; end;
我们也可以一次性取出游标的所有数据,放入到table类型变量中:
declare --声明游标变量 ,加入参数 cursor cur_emp(v_deptno number) is select * from emp where deptno=v_deptno; --声明table类型 type emp_table_type is table of emp%rowtype index by binary_integer; -- 声明table类型变量 v_emp emp_table_type; begin --打印部门编号为10的员工的信息 --打开游标 open cur_emp(10); --一次性取出游标中的所有数据 ,放入table类型变量中 fetch cur_emp bulk collect into v_emp; --关闭游标 close cur_emp; --循环输出table类型变量中的内容 for v_i in v_emp.first .. v_emp.last loop dbms_output.put_line('员工编号:'||v_emp(v_i).empno||',员工姓名:'||v_emp(v_i).ename); end loop; end;
游标for循环
每次使用游标都需要打开和关闭游标,比较麻烦,我们可以使用游标for循环来简化游标的使用方式。
举例:打印部门表所有内容
declare -- 声明游标变量 cursor cur_dept is select * from dept; begin -- 使用游标for循环不需要显式的打开或者关闭游标 -- 循环变量也不需要显式声明,该游标变量是行类型rowtype类型或者记录类型record for v_dept in cur_dept loop dbms_output.put_line('部门编号:'||v_dept.deptno||',部门名称:'||v_dept.dname); end loop; end;
游标for循环还可以继续简写:
begin -- 游标for循环简写 for v_dept in (select * from dept) loop dbms_output.put_line('部门编号:'||v_dept.deptno||',部门名称:'||v_dept.dname); end loop; end;
游标变量类型(非重点)
以前的游标没有办法从不同的表中取数据,在大项目中,有可能需要声明很多游标变量,非常繁琐,我们可以使用
游标变量类型来解决这个问题。
举例:声明游标变量类型,先从打印员工表数据,再打印部门表数据。
declare --声明游标变量类型 type cur_test_type is ref cursor; -- 声明cur_test_type类型的游标变量 cur_test cur_test_type; v_emp emp%rowtype; v_dept dept%rowtype; begin -- 先打印员工表所有数据 --打开游标,同时告诉该从哪个表取数据 open cur_test for select * from emp; loop fetch cur_test into v_emp; exit when cur_test%notfound; dbms_output.put_line('员工编号:'||v_emp.empno||',员工姓名:'||v_emp.ename); end loop; --关闭游标 close cur_test; --再使用cur_test游标变量从部门表取数据 open cur_test for select * from dept; loop fetch cur_test into v_dept; exit when cur_test%notfound; dbms_output.put_line('部门编号:'||v_dept.deptno||',员工姓名:'||v_dept.dname); end loop; --关闭游标 close cur_test; end;
隐含游标
oracle中也有隐含游标,在所有增删改语句执行之后,数据库会默认为我们创建一个隐含游标,名字叫sql。我们可
以访问隐含游标的属性。隐含游标不需要打开或者关闭。
举例:删除员工,如果员工编号不存在,打印错误信息
begin delete from emp where empno=9999; --通过隐含游标判断是否删除成功 if sql%found then dbms_output.put_line('删除成功'); else dbms_output.put_line('删除失败'); end if; end;