SQL游标
/*
在执行执行增删改查语句的时候,Oracle都会开辟一块内存空间,
用来暂时存放收到SQL语句影响的数据。
这块内存空间就被称为游标区域,我们可以借助于游标来分析这些受到影响的数据
*/
/*
游标的分类:
1、隐式游标:
增删改查语句都会由隐式游标,也就是说,我们可以通过隐式游标来分析受到增删改查语句影响的数据。
2、显式游标:
在PL/SQL种执行select语句的特殊要求:
(1):select语句只能返回一条记录
(2):必须搭配使用into
也就是说:显示游标专门用来从数据库种查询多条数据的;
*/
游标的属性
/*
游标属性包括四种:
%rowcount 受SQL影响的行数
%found boolean值,是否还有数据
%notfound boolean值,是否已无数据
%isopen 游标是否打开
显示游标和隐式游标都有这四个属性。但是使用方法和含义却不相同。
*/
隐式游标
/*
在使用游标的时候,需要使用游标名称作为前缀。但是隐式游标没有名称,
所以在使用隐式游标的时候采取统一的一个名称SQL。
也就是说:隐式游标同意使用SQL前缀,例如:
SQL%rowcount 受SQL影响的行数
SQL%found boolean值,是否还有数据
SQL%notfound boolean值,是否已无数据
SQL%isopen 总是false
*/
declare
v_count number(3);
begin
delete from emp where deptno = 10;
v_count :=SQL%rowcount;
dbms_output.put_line('被删除的数据的条数是:'|| v_count);
end;
显示游标
/*
显式游标的使用:
1、可以用于暂存查询取出的多行结果,然后一行一行的处理。
2、显示游标就是专门用来查询多条数据的
3、按行处理查询返回的多行结果
4、显示游标首先将查询出的多行数据暂存在游标区域中,然后在PL/SQL中
借助循环语句手动的控制游标的多行操作,每次取出一条进行处理,直到取出
游标中所有的数据为止。
显式游标和隐式游标不同,在调用隐式游标的时候,通过SQL前缀来调用(SQL%rowcount),
而显式游标都有自己的名称,在调用时使用显示游标的名称,作为属性的前缀(游标名%rowcount)。
*/
declare
-- 1、声明游标,一个显示游标,就是和一个有效的select语句绑死的
cursor cur_emp is select * from emp;
v_emp emp%rowtype;
begin
-- 2、打开游标,就是执行了游标绑定的SQL语句,并且把受到影响的数据放入到了游标区域中
open cur_emp;
-- 3、取出游标中的一条数据装入记录类型的变量中
fetch cur_emp into v_emp;
-- 从记录类型的变量中取出查询数据
dbms_output.put_line(v_emp.empno||','||v_emp.ename||','||
v_emp.job||','||v_emp.mgr||','||v_emp.hiredate||','||
v_emp.sal||','||nvl(v_emp.comm,0)||','||v_emp.deptno);
-- 关闭游标,清空游标区域
close cur_emp;
-- 那么问题来了,我们不是说可以从显式游标中取出多条数据吗?但我们只取了一条,那是因为我们没有用循环。
end;
-- 使用loop循环和%notfound来遍历游标
declare
-- 1、声明游标,一个显示游标,就是和一个有效的select语句绑死的
cursor cur_emp is select * from emp;
v_emp emp%rowtype;
begin
--dbms_output.put_line('查询游标的总条数'||cur_emp%rowtype);
-- 在游标没有打开之前或者关闭之后,是无法使用的,就会导致无效的游标错误
-- 在关闭之后,如果需要重新使用游标,需要重新打开游标
-- 2、打开游标,就是执行了游标绑定的SQL语句,并且把受到影响的数据放入到了游标区域中
open cur_emp;
loop
-- 3、取出游标中的一条数据装入记录类型的变量中
fetch cur_emp into v_emp;
exit when cur_emp%notfound; -- 当游标中没有数据的时候,退出循环。
dbms_output.put_line(v_emp.empno||','||v_emp.ename||','||
v_emp.job||','||v_emp.mgr||','||v_emp.hiredate||','||
v_emp.sal||','||nvl(v_emp.comm,0)||','||v_emp.deptno);
end loop;
dbms_output.put_line('查询游标的总条数'||cur_emp%rowcount);
close cur_emp;
--dbms_output.put_line('查询游标的总条数'||cur_emp%rowtype);
end;
-- 使用while循环和%found搭配使用分析游标数据
declare
cursor cur_emp is select * from emp;
v_emp emp%rowtype;
begin
open cur_emp;
fetch cur_emp into v_emp;--取出游标中的一条数据装入记录类型的变量中
-- 如果把这句放在while里面,那么游标里面的值就是0
while(cur_emp%found) loop
-- fetch cur_emp into v_emp;
dbms_output.put_line(v_emp.empno||','||v_emp.ename||','||
v_emp.job||','||v_emp.mgr||','||v_emp.hiredate||','||
v_emp.sal||','||nvl(v_emp.comm,0)||','||v_emp.deptno);
fetch cur_emp into v_emp;--迭代,如果没有的话,就会一直存入第一条数据,造成内容溢出。
end loop;
dbms_output.put_line('查询游标的总条数'||cur_emp%rowcount);
close cur_emp;
end;
-- 使用for循环,可以简化游标的开发,Oracle会自动的声明记录类型的变量,Oracle会自动的open,fetch、close游标。
declare
cursor cur_emp is select * from emp;
begin
-- Oracle会自动的声明记录类型的变量v_emp,类型是emp%rowtype;
-- for循环会自动 open
for v_emp in cur_emp loop
dbms_output.put_line(v_emp.empno||','||v_emp.ename||','||
v_emp.job||','||v_emp.mgr||','||v_emp.hiredate||','||
v_emp.sal||','||nvl(v_emp.comm,0)||','||v_emp.deptno);
end loop;
end;
-- 带参数的游标
/*
也就是带条件的游标,因为有时候我们不需要查询所有。
*/
declare
cursor cur_emp(v_deptno number) is select * from emp where deptno=v_deptno;
v_emp emp%rowtype;
begin
open cur_emp(20);--查询20部门
loop
fetch cur_emp into v_emp;
dbms_output.put_line(v_emp.empno||','||v_emp.ename||','||
v_emp.job||','||v_emp.mgr||','||v_emp.hiredate||','||
v_emp.sal||','||nvl(v_emp.comm,0)||','||v_emp.deptno);
exit when cur_emp%notfound; -- 但游标中没有数据的时候,退出循环。
end loop;
end;
使用游标更新或删除行数据
允许使用游标删除或更新活动集中的行
声明游标时必须使用 select....for update 语句
declare
v_emp emp%rowtype;
cursor mycur is select * from emp where deptno=20 for update;
begin
open mycur;
fetch mycur into v_emp;
while mycur%found loop
-- where current of 游标名; 对游标读取的所在行进行更新和删除
update emp set sal = 100 where current of mycur;
fetch mycur into v_emp;
end loop;
close mycur;
end;
REF游标
/*
REF 游标
*/
-- 查询所有的员工信息
declare
-- 声明 ref 游标类型
type myret is ref cursor;
-- 声明ref游标类型的变量
cur_emp myret;
-- 声明变量
v_emp emp%rowtype;
begin
-- 开启 ref 游标
open cur_emp for select * from emp;
fetch cur_emp into v_emp;
while cur_emp%found loop
dbms_output.put_line(v_emp.empno||','||v_emp.ename||','||
v_emp.job||','||v_emp.mgr||','||v_emp.hiredate||','||
v_emp.sal||','||nvl(v_emp.comm,0)||','||v_emp.deptno);
fetch cur_emp into v_emp;
end loop;
close cur_emp;
end;
更多推荐
SQL游标——PL/SQL教程(三)
发布评论